diff --git a/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj b/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
index 4efe500bb7..fb51942120 100644
--- a/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
+++ b/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
@@ -63,7 +63,6 @@
-
diff --git a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/BindingExtension.cs b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/BindingExtension.cs
index e0adbcdbbc..223716ae3b 100644
--- a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/BindingExtension.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/BindingExtension.cs
@@ -33,7 +33,7 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
return ProvideTypedValue(serviceProvider);
}
- public IBinding ProvideTypedValue(IServiceProvider serviceProvider)
+ public Binding ProvideTypedValue(IServiceProvider serviceProvider)
{
var descriptorContext = (ITypeDescriptorContext)serviceProvider;
diff --git a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlCompiler.cs b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlCompiler.cs
index 1d7d93596e..facac748c3 100644
--- a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlCompiler.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlCompiler.cs
@@ -39,10 +39,9 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
InsertBefore(new AvaloniaXamlIlTransformInstanceAttachedProperties());
InsertAfter(new AvaloniaXamlIlAvaloniaPropertyResolver());
- InsertBefore(new AvaloniaXamlIlBindingPropertyAssignmentsTransformer());
- InsertBefore(
+ InsertBefore(
new AvaloniaXamlIlSelectorTransformer(),
new AvaloniaXamlIlSetterTransformer(),
new AvaloniaXamlIlControlTemplateTargetTypeMetadataTransformer(),
diff --git a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlLanguage.cs b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlLanguage.cs
index 0de9e7942b..581dbcdac7 100644
--- a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlLanguage.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlLanguage.cs
@@ -50,24 +50,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
typeSystem.GetType("Portable.Xaml.Markup.UsableDuringInitializationAttribute"),
typeSystem.GetType("Avalonia.Metadata.UsableDuringInitializationAttribute"),
},
- MarkupExtensionCustomResultTypes =
- {
- bindingType,
- typeSystem.GetType("Avalonia.UnsetValueType")
- },
- MarkupExtensionCustomResultHandler =
- runtimeHelpers.FindMethod(m => m.Name == "ApplyNonMatchingMarkupExtensionV1"),
InnerServiceProviderFactoryMethod =
runtimeHelpers.FindMethod(m => m.Name == "CreateInnerServiceProviderV1"),
- ShouldIgnoreMarkupExtensionCustomResultForProperty = (prop, customType) =>
- {
- if (prop.Name == "Value" && prop.Setter?.DeclaringType.FullName == "Avalonia.Styling.Setter")
- return true;
- if (customType.Equals(bindingType) &&
- prop.CustomAttributes.Any(a => a.Type.Equals(assignBindingAttribute)))
- return true;
- return false;
- },
ProvideValueTargetPropertyEmitter = XamlIlAvaloniaPropertyHelper.Emit,
};
rv.CustomAttributeResolver = new AttributeResolver(typeSystem, rv);
diff --git a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AddNameScopeRegistration.cs b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AddNameScopeRegistration.cs
index c400995fd1..f9bc440b6b 100644
--- a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AddNameScopeRegistration.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AddNameScopeRegistration.cs
@@ -1,4 +1,5 @@
using System;
+using System.Linq;
using XamlIl.Ast;
using XamlIl.Transform;
using XamlIl.TypeSystem;
@@ -11,21 +12,50 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{
if (node is XamlIlPropertyAssignmentNode pa
&& pa.Property.Name == "Name"
- && pa.Property.Setter.DeclaringType.FullName == "Avalonia.StyledElement")
- return new ScopeRegistrationNode(pa);
+ && pa.Property.DeclaringType.FullName == "Avalonia.StyledElement")
+ {
+ if (context.ParentNodes().FirstOrDefault() is XamlIlManipulationGroupNode mg
+ && mg.Children.OfType().Any())
+ return node;
+
+ IXamlIlAstValueNode value = null;
+ for (var c = 0; c < pa.Values.Count; c++)
+ if (pa.Values[c].Type.GetClrType().Equals(context.Configuration.WellKnownTypes.String))
+ {
+ value = pa.Values[c];
+ if (!(value is XamlIlAstTextNode))
+ {
+ var local = new XamlIlAstCompilerLocalNode(value);
+ // Wrap original in local initialization
+ pa.Values[c] = new XamlIlAstLocalInitializationNodeEmitter(value, value, local);
+ // Use local
+ value = local;
+ }
+
+ break;
+ }
+
+ if (value != null)
+ return new XamlIlManipulationGroupNode(pa)
+ {
+ Children =
+ {
+ pa,
+ new ScopeRegistrationNode(value)
+ }
+ };
+ }
return node;
}
class ScopeRegistrationNode : XamlIlAstNode, IXamlIlAstManipulationNode, IXamlIlAstEmitableNode
{
+ private readonly IXamlIlType _targetType;
public IXamlIlAstValueNode Value { get; set; }
- private IXamlIlProperty _property;
-
- public ScopeRegistrationNode(XamlIlPropertyAssignmentNode pa) : base(pa)
+ public ScopeRegistrationNode(IXamlIlAstValueNode value) : base(value)
{
- _property = pa.Property;
- Value = pa.Value;
+ Value = value;
}
public override void VisitChildren(IXamlIlAstVisitor visitor)
@@ -36,24 +66,13 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
var exts = context.Configuration.TypeSystem.GetType("Avalonia.Controls.NameScopeExtensions");
var findNameScope = exts.FindMethod(m => m.Name == "FindNameScope");
var registerMethod = findNameScope.ReturnType.FindMethod(m => m.Name == "Register");
- using (var nameLoc = context.GetLocal(context.Configuration.WellKnownTypes.String))
- using (var targetLoc = context.GetLocal(_property.Setter.DeclaringType))
+ using (var targetLoc = context.GetLocal(context.Configuration.WellKnownTypes.Object))
using (var nameScopeLoc = context.GetLocal(findNameScope.ReturnType))
{
var exit = codeGen.DefineLabel();
-
- // var target = {target}
codeGen
- .Castclass(_property.Setter.DeclaringType)
- .Stloc(targetLoc.Local);
-
- // var name = {EmitName()}
- context.Emit(Value, codeGen, _property.PropertyType);
- codeGen.Stloc(nameLoc.Local)
- // target.Name = name
- .Ldloc(targetLoc.Local)
- .Ldloc(nameLoc.Local)
- .EmitCall(_property.Setter)
+ // var target = {pop}
+ .Stloc(targetLoc.Local)
// var scope = target.FindNameScope()
.Ldloc(targetLoc.Local)
.Castclass(findNameScope.Parameters[0])
@@ -62,8 +81,9 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
// if({scope} != null) goto call;
.Ldloc(nameScopeLoc.Local)
.Brfalse(exit)
- .Ldloc(nameScopeLoc.Local)
- .Ldloc(nameLoc.Local)
+ .Ldloc(nameScopeLoc.Local);
+ context.Emit(Value, codeGen, Value.Type.GetClrType());
+ codeGen
.Ldloc(targetLoc.Local)
.EmitCall(registerMethod)
.MarkLabel(exit);
diff --git a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlAvaloniaPropertyResolver.cs b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlAvaloniaPropertyResolver.cs
index ed17e59e14..f95ad132ad 100644
--- a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlAvaloniaPropertyResolver.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlAvaloniaPropertyResolver.cs
@@ -8,14 +8,14 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{
public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node)
{
- if (node is XamlIlAstClrPropertyReference prop)
+ if (node is XamlIlAstClrProperty prop)
{
- var n = prop.Property.Name + "Property";
+ var n = prop.Name + "Property";
var field =
- (prop.Property.Getter ?? prop.Property.Setter).DeclaringType.Fields
+ prop.DeclaringType.Fields
.FirstOrDefault(f => f.Name == n);
if (field != null)
- prop.Property = new XamlIlAvaloniaProperty(prop.Property, field);
+ return new XamlIlAvaloniaProperty(prop, field, context.GetAvaloniaTypes());
}
return node;
diff --git a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlBindingPropertyAssignmentsTransformer.cs b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlBindingPropertyAssignmentsTransformer.cs
deleted file mode 100644
index 17b057a745..0000000000
--- a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlBindingPropertyAssignmentsTransformer.cs
+++ /dev/null
@@ -1,114 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using XamlIl.Ast;
-using XamlIl.Transform;
-using XamlIl.TypeSystem;
-
-namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
-{
- public class AvaloniaXamlIlBindingPropertyAssignmentsTransformer : IXamlIlAstTransformer
- {
- public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node)
- {
- if (node is XamlIlAstXamlPropertyValueNode pv
- && pv.Property.GetClrProperty() is IXamlIlAvaloniaProperty ap
- && pv.Values.Count == 1)
- {
- var types = context.GetAvaloniaTypes();
-
- var vn = pv.Values[0];
- if (vn.Type.GetClrType().Equals(XamlIlPseudoType.Null))
- return node;
-
- if (pv.Property.GetClrProperty().CustomAttributes
- .Any(a => a.Type.Equals(types.AssignBindingAttribute)))
- return node;
-
- // Special handling for markup extensions
- if (vn.Type.IsMarkupExtension)
- {
- if (XamlIlTransformHelpers
- .GetMarkupExtensionProvideValueAlternatives(context, vn.Type.GetClrType())
- .Any(x => types.IBinding.IsAssignableFrom(x.ReturnType)))
- {
- if (XamlIlTransformHelpers.TryConvertMarkupExtension(context, pv.Values[0],
- new AssignBindingProperty(types, ap), out var ext))
- return ext;
- }
- }
- else if (types.IBinding.IsAssignableFrom(vn.Type.GetClrType()))
- {
- pv.Property = new XamlIlAstClrPropertyReference(pv.Property, new AssignBindingProperty(types, ap));
- }
- }
-
- return node;
- }
-
- class AssignBindingProperty : IXamlIlAvaloniaProperty
- {
- public AssignBindingProperty(
- AvaloniaXamlIlWellKnownTypes types,
- IXamlIlAvaloniaProperty property
- )
- {
- PropertyType = types.IBinding;
- AvaloniaProperty = property.AvaloniaProperty;
- CustomAttributes = property.CustomAttributes;
- Name = property.Name;
- Setter = new SetterMethod(types, (property.Setter ?? property.Getter).DeclaringType,
- AvaloniaProperty);
- }
-
- public bool Equals(IXamlIlProperty other) =>
- other is AssignBindingProperty abp && abp.AvaloniaProperty.Equals(AvaloniaProperty);
-
- public string Name { get; }
- public IXamlIlType PropertyType { get; }
- public IXamlIlMethod Setter { get; }
- public IXamlIlMethod Getter { get; }
- public IReadOnlyList CustomAttributes { get; }
- public IXamlIlField AvaloniaProperty { get; }
-
- class SetterMethod : IXamlIlCustomEmitMethod
- {
- private readonly AvaloniaXamlIlWellKnownTypes _types;
- private readonly IXamlIlField _avaloniaProperty;
-
- public SetterMethod(AvaloniaXamlIlWellKnownTypes types,
- IXamlIlType declaringType,
- IXamlIlField avaloniaProperty)
- {
- _types = types;
- _avaloniaProperty = avaloniaProperty;
- Parameters = new[] {types.AvaloniaObject, types.IBinding};
- ReturnType = types.XamlIlTypes.Void;
- DeclaringType = declaringType;
- Name = "Bind_" + avaloniaProperty.Name;
- }
-
- public bool Equals(IXamlIlMethod other) =>
- other is SetterMethod sm && sm._avaloniaProperty.Equals(_avaloniaProperty);
-
- public string Name { get; }
- public bool IsPublic => true;
- public bool IsStatic => true;
- public IXamlIlType ReturnType { get; }
- public IReadOnlyList Parameters { get; }
- public IXamlIlType DeclaringType { get; }
- public void EmitCall(IXamlIlEmitter emitter)
- {
- using (var bloc = emitter.LocalsPool.GetLocal(_types.IBinding))
- emitter
- .Stloc(bloc.Local)
- .Ldsfld(_avaloniaProperty)
- .Ldloc(bloc.Local)
- // TODO: provide anchor?
- .Ldnull();
- emitter.EmitCall(_types.AvaloniaObjectBindMethod, true);
- }
- }
- }
- }
-}
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 11df8bfa82..a7f7603012 100644
--- a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlSelectorTransformer.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlSelectorTransformer.cs
@@ -34,7 +34,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
if (!(pn.Values[0] is XamlIlAstTextNode tn))
throw new XamlIlParseException("Selector property should be a text node", node);
- var selectorType = pn.Property.GetClrProperty().PropertyType;
+ var selectorType = pn.Property.GetClrProperty().Getter.ReturnType;
var initialNode = new XamlIlSelectorInitialNode(node, selectorType);
XamlIlSelectorNode Create(IEnumerable syntax,
Func typeResolver)
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 28a8675903..0e7ea34bb7 100644
--- a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlSetterTransformer.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlSetterTransformer.cs
@@ -53,21 +53,56 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
.OfType().FirstOrDefault(p => p.Property.GetClrProperty().Name == "Value");
if (valueProperty?.Values?.Count == 1 && valueProperty.Values[0] is XamlIlAstTextNode)
{
+ var propType = avaloniaPropertyNode.Property.Getter?.ReturnType
+ ?? avaloniaPropertyNode.Property.Setters.First().Parameters[0];
if (!XamlIlTransformHelpers.TryGetCorrectlyTypedValue(context, valueProperty.Values[0],
- avaloniaPropertyNode.Property.PropertyType, out var converted))
+ propType, out var converted))
throw new XamlIlParseException(
- $"Unable to convert property value to {avaloniaPropertyNode.Property.PropertyType.GetFqn()}",
+ $"Unable to convert property value to {propType.GetFqn()}",
valueProperty.Values[0]);
- valueProperty.Values = new List
- {
- new XamlIlAstRuntimeCastNode(converted, converted,
- new XamlIlAstClrTypeReference(converted, context.Configuration.WellKnownTypes.Object, false))
- };
+ valueProperty.Property = new SetterValueProperty(valueProperty.Property,
+ on.Type.GetClrType(), propType, context.GetAvaloniaTypes());
}
return node;
}
-
+
+ class SetterValueProperty : XamlIlAstClrProperty
+ {
+ public SetterValueProperty(IXamlIlLineInfo line, IXamlIlType setterType, IXamlIlType targetType,
+ AvaloniaXamlIlWellKnownTypes types)
+ : base(line, "Value", setterType, null)
+ {
+ Getter = setterType.Methods.First(m => m.Name == "get_Value");
+ var method = setterType.Methods.First(m => m.Name == "set_Value");
+ Setters.Add(new XamlIlDirectCallPropertySetter(method, types.IBinding));
+ Setters.Add(new XamlIlDirectCallPropertySetter(method, types.UnsetValueType));
+ Setters.Add(new XamlIlDirectCallPropertySetter(method, targetType));
+ }
+
+ class XamlIlDirectCallPropertySetter : IXamlIlPropertySetter
+ {
+ private readonly IXamlIlMethod _method;
+ private readonly IXamlIlType _type;
+ public IXamlIlType TargetType { get; }
+ public PropertySetterBinderParameters BinderParameters { get; } = new PropertySetterBinderParameters();
+ public IReadOnlyList Parameters { get; }
+ public void Emit(IXamlIlEmitter codegen)
+ {
+ if (_type.IsValueType)
+ codegen.Box(_type);
+ codegen.EmitCall(_method, true);
+ }
+
+ public XamlIlDirectCallPropertySetter(IXamlIlMethod method, IXamlIlType type)
+ {
+ _method = method;
+ _type = type;
+ Parameters = new[] {type};
+ TargetType = method.ThisOrFirstParameter();
+ }
+ }
+ }
}
}
diff --git a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlTransformInstanceAttachedProperties.cs b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlTransformInstanceAttachedProperties.cs
index 1b3b1d7047..bbacef43dd 100644
--- a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlTransformInstanceAttachedProperties.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlTransformInstanceAttachedProperties.cs
@@ -56,10 +56,9 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
avaloniaPropertyType.GenericArguments[0] :
context.Configuration.WellKnownTypes.Object;
- return new XamlIlAstClrPropertyReference(prop,
- new AvaloniaAttachedInstanceProperty(prop.Name, context.Configuration,
+ return new AvaloniaAttachedInstanceProperty(prop, context.Configuration,
declaringType, propertyType, avaloniaPropertyType, avaloniaObject,
- avaloniaPropertyField));
+ avaloniaPropertyField);
}
}
@@ -71,7 +70,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
return node;
}
- class AvaloniaAttachedInstanceProperty : IXamlIlAvaloniaProperty
+ class AvaloniaAttachedInstanceProperty : XamlIlAstClrProperty, IXamlIlAvaloniaProperty
{
private readonly XamlIlTransformerConfiguration _config;
private readonly IXamlIlType _declaringType;
@@ -79,13 +78,16 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
private readonly IXamlIlType _avaloniaObject;
private readonly IXamlIlField _field;
- public AvaloniaAttachedInstanceProperty(string name,
+ public AvaloniaAttachedInstanceProperty(XamlIlAstNamePropertyReference prop,
XamlIlTransformerConfiguration config,
IXamlIlType declaringType,
IXamlIlType type,
IXamlIlType avaloniaPropertyType,
IXamlIlType avaloniaObject,
- IXamlIlField field)
+ IXamlIlField field) : base(prop, prop.Name,
+ declaringType, null)
+
+
{
_config = config;
_declaringType = declaringType;
@@ -97,72 +99,50 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
_avaloniaObject = avaloniaObject;
_field = field;
- Name = name;
PropertyType = type;
- Setter = new SetterMethod(this);
+ Setters.Add(new SetterMethod(this));
Getter = new GetterMethod(this);
}
- public IXamlIlField AvaloniaProperty => _field;
- public bool Equals(IXamlIlProperty other) =>
- other is AvaloniaAttachedInstanceProperty ap && ap._field.Equals(_field);
-
- public string Name { get; }
- public IXamlIlType PropertyType { get; }
- public IXamlIlMethod Setter { get; }
- public IXamlIlMethod Getter { get; }
- public IReadOnlyList CustomAttributes { get; } = new List();
-
- class Method
- {
- public AvaloniaAttachedInstanceProperty Parent { get; }
- public bool IsPublic => true;
- public bool IsStatic => true;
- public string Name { get; protected set; }
- public IXamlIlType DeclaringType { get; }
- public Method(AvaloniaAttachedInstanceProperty parent)
- {
- Parent = parent;
- DeclaringType = parent._declaringType;
- }
+ public IXamlIlType PropertyType { get; }
- public bool Equals(IXamlIlMethod other) =>
- other is Method m && m.Name == Name && m.DeclaringType.Equals(DeclaringType);
- }
+ public IXamlIlField AvaloniaProperty => _field;
- class SetterMethod : Method, IXamlIlCustomEmitMethod
+ class SetterMethod : IXamlIlPropertySetter
{
- public SetterMethod(AvaloniaAttachedInstanceProperty parent) : base(parent)
+ private readonly AvaloniaAttachedInstanceProperty _parent;
+
+ public SetterMethod(AvaloniaAttachedInstanceProperty parent)
{
- Name = "AvaloniaObject:SetValue_" + Parent.Name;
- Parameters = new[] {Parent._avaloniaObject, Parent.PropertyType};
+ _parent = parent;
+ Parameters = new[] {_parent._avaloniaObject, _parent.PropertyType};
}
- public IXamlIlType ReturnType => Parent._config.WellKnownTypes.Void;
+ public IXamlIlType TargetType => _parent.DeclaringType;
+ public PropertySetterBinderParameters BinderParameters { get; } = new PropertySetterBinderParameters();
public IReadOnlyList Parameters { get; }
-
- public void EmitCall(IXamlIlEmitter emitter)
+ public void Emit(IXamlIlEmitter emitter)
{
- var so = Parent._config.WellKnownTypes.Object;
- var method = Parent._avaloniaObject
+ var so = _parent._config.WellKnownTypes.Object;
+ var method = _parent._avaloniaObject
.FindMethod(m => m.IsPublic && !m.IsStatic && m.Name == "SetValue"
&&
m.Parameters.Count == 3
- && m.Parameters[0].Equals(Parent._avaloniaPropertyType)
+ && m.Parameters[0].Equals(_parent._avaloniaPropertyType)
&& m.Parameters[1].Equals(so)
&& m.Parameters[2].IsEnum
);
if (method == null)
throw new XamlIlTypeSystemException(
"Unable to find SetValue(AvaloniaProperty, object, BindingPriority) on AvaloniaObject");
- using (var loc = emitter.LocalsPool.GetLocal(Parent.PropertyType))
+ using (var loc = emitter.LocalsPool.GetLocal(_parent.PropertyType))
emitter
.Stloc(loc.Local)
- .Ldsfld(Parent._field)
+ .Ldsfld(_parent._field)
.Ldloc(loc.Local);
- if(Parent.PropertyType.IsValueType)
- emitter.Box(Parent.PropertyType);
+ if(_parent.PropertyType.IsValueType)
+ emitter.Box(_parent.PropertyType);
emitter
.Ldc_I4(0)
.EmitCall(method);
@@ -170,14 +150,24 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
}
}
- class GetterMethod : Method, IXamlIlCustomEmitMethod
+ class GetterMethod : IXamlIlCustomEmitMethod
{
- public GetterMethod(AvaloniaAttachedInstanceProperty parent) : base(parent)
+ public GetterMethod(AvaloniaAttachedInstanceProperty parent)
{
+ Parent = parent;
+ DeclaringType = parent._declaringType;
Name = "AvaloniaObject:GetValue_" + Parent.Name;
Parameters = new[] {parent._avaloniaObject};
}
+ public AvaloniaAttachedInstanceProperty Parent { get; }
+ public bool IsPublic => true;
+ public bool IsStatic => true;
+ public string Name { get; protected set; }
+ public IXamlIlType DeclaringType { get; }
+
+ public bool Equals(IXamlIlMethod other) =>
+ other is GetterMethod m && m.Name == Name && m.DeclaringType.Equals(DeclaringType);
public IXamlIlType ReturnType => Parent.PropertyType;
public IReadOnlyList Parameters { get; }
public void EmitCall(IXamlIlEmitter emitter)
diff --git a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlTransitionsTypeMetadataTransformer.cs b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlTransitionsTypeMetadataTransformer.cs
index 11e20a9dab..36c5cc2b98 100644
--- a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlTransitionsTypeMetadataTransformer.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlTransitionsTypeMetadataTransformer.cs
@@ -12,7 +12,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
foreach (var ch in on.Children)
{
if (ch is XamlIlAstXamlPropertyValueNode pn
- && pn.Property.GetClrProperty().PropertyType.Equals(context.GetAvaloniaTypes().Transitions))
+ && pn.Property.GetClrProperty().Getter?.ReturnType.Equals(context.GetAvaloniaTypes().Transitions) == true)
{
for (var c = 0; c < pn.Values.Count; c++)
{
diff --git a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs
index 83c35605e1..b57c26c241 100644
--- a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs
@@ -7,14 +7,17 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{
public IXamlIlType AvaloniaObject { get; }
public IXamlIlType IAvaloniaObject { get; }
+ public IXamlIlType BindingPriority { get; }
public IXamlIlType AvaloniaObjectExtensions { get; }
public IXamlIlType AvaloniaProperty { get; }
public IXamlIlType IBinding { get; }
public IXamlIlMethod AvaloniaObjectBindMethod { get; }
+ public IXamlIlMethod AvaloniaObjectSetValueMethod { get; }
public IXamlIlType IDisposable { get; }
public XamlIlTypeWellKnownTypes XamlIlTypes { get; }
public IXamlIlType Transitions { get; }
public IXamlIlType AssignBindingAttribute { get; }
+ public IXamlIlType UnsetValueType { get; }
public AvaloniaXamlIlWellKnownTypes(XamlIlAstTransformationContext ctx)
{
@@ -23,6 +26,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
IAvaloniaObject = ctx.Configuration.TypeSystem.GetType("Avalonia.IAvaloniaObject");
AvaloniaObjectExtensions = ctx.Configuration.TypeSystem.GetType("Avalonia.AvaloniaObjectExtensions");
AvaloniaProperty = ctx.Configuration.TypeSystem.GetType("Avalonia.AvaloniaProperty");
+ BindingPriority = ctx.Configuration.TypeSystem.GetType("Avalonia.Data.BindingPriority");
IBinding = ctx.Configuration.TypeSystem.GetType("Avalonia.Data.IBinding");
IDisposable = ctx.Configuration.TypeSystem.GetType("System.IDisposable");
Transitions = ctx.Configuration.TypeSystem.GetType("Avalonia.Animation.Transitions");
@@ -30,6 +34,9 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
AvaloniaObjectBindMethod = AvaloniaObjectExtensions.FindMethod("Bind", IDisposable, false, IAvaloniaObject,
AvaloniaProperty,
IBinding, ctx.Configuration.WellKnownTypes.Object);
+ UnsetValueType = ctx.Configuration.TypeSystem.GetType("Avalonia.UnsetValueType");
+ AvaloniaObjectSetValueMethod = AvaloniaObject.FindMethod("SetValue", XamlIlTypes.Void,
+ false, AvaloniaProperty, XamlIlTypes.Object, BindingPriority);
}
}
diff --git a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/XamlIlAvaloniaPropertyHelper.cs b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/XamlIlAvaloniaPropertyHelper.cs
index e090b42d17..106541ec5c 100644
--- a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/XamlIlAvaloniaPropertyHelper.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/XamlIlAvaloniaPropertyHelper.cs
@@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Xml;
using Avalonia.Markup.Xaml.Parsers;
+using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers;
using Avalonia.Utilities;
using XamlIl;
using XamlIl.Ast;
@@ -13,13 +15,25 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
{
class XamlIlAvaloniaPropertyHelper
{
- public static bool Emit(XamlIlEmitContext context, IXamlIlEmitter emitter, IXamlIlProperty property)
+ public static bool Emit(XamlIlEmitContext context, IXamlIlEmitter emitter, XamlIlAstClrProperty property)
{
if (property is IXamlIlAvaloniaProperty ap)
{
emitter.Ldsfld(ap.AvaloniaProperty);
return true;
}
+ var type = property.DeclaringType;
+ var name = property.Name + "Property";
+ var found = type.Fields.FirstOrDefault(f => f.IsStatic && f.Name == name);
+ if (found == null)
+ return false;
+
+ emitter.Ldsfld(found);
+ return true;
+ }
+
+ public static bool Emit(XamlIlEmitContext context, IXamlIlEmitter emitter, IXamlIlProperty property)
+ {
var type = (property.Getter ?? property.Setter).DeclaringType;
var name = property.Name + "Property";
var found = type.Fields.FirstOrDefault(f => f.IsStatic && f.Name == name);
@@ -54,8 +68,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
}
var clrProperty =
- ((XamlIlAstClrPropertyReference)new XamlIlPropertyReferenceResolver().Transform(context,
- forgedReference)).Property;
+ ((XamlIlAstClrProperty)new XamlIlPropertyReferenceResolver().Transform(context,
+ forgedReference));
return new XamlIlAvaloniaPropertyNode(lineInfo,
context.Configuration.TypeSystem.GetType("Avalonia.AvaloniaProperty"),
clrProperty);
@@ -64,13 +78,13 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
class XamlIlAvaloniaPropertyNode : XamlIlAstNode, IXamlIlAstValueNode, IXamlIlAstEmitableNode
{
- public XamlIlAvaloniaPropertyNode(IXamlIlLineInfo lineInfo, IXamlIlType type, IXamlIlProperty property) : base(lineInfo)
+ public XamlIlAvaloniaPropertyNode(IXamlIlLineInfo lineInfo, IXamlIlType type, XamlIlAstClrProperty property) : base(lineInfo)
{
Type = new XamlIlAstClrTypeReference(this, type, false);
Property = property;
}
- public IXamlIlProperty Property { get; }
+ public XamlIlAstClrProperty Property { get; }
public IXamlIlAstTypeReference Type { get; }
public XamlIlNodeEmitResult Emit(XamlIlEmitContext context, IXamlIlEmitter codeGen)
@@ -81,29 +95,92 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
}
}
- interface IXamlIlAvaloniaProperty : IXamlIlProperty
+ interface IXamlIlAvaloniaProperty
{
IXamlIlField AvaloniaProperty { get; }
}
- class XamlIlAvaloniaProperty : IXamlIlAvaloniaProperty
+ class XamlIlAvaloniaProperty : XamlIlAstClrProperty, IXamlIlAvaloniaProperty
{
- private readonly IXamlIlProperty _original;
-
public IXamlIlField AvaloniaProperty { get; }
- public XamlIlAvaloniaProperty(IXamlIlProperty original, IXamlIlField field)
+ public XamlIlAvaloniaProperty(XamlIlAstClrProperty original, IXamlIlField field,
+ AvaloniaXamlIlWellKnownTypes types)
+ :base(original, original.Name, original.DeclaringType, original.Getter, original.Setters)
{
- _original = original;
AvaloniaProperty = field;
+ CustomAttributes = original.CustomAttributes;
+ if (!original.CustomAttributes.Any(ca => ca.Type.Equals(types.AssignBindingAttribute)))
+ Setters.Insert(0, new BindingSetter(types, original.DeclaringType, field));
+
+ Setters.Insert(0, new UnsetValueSetter(types, original.DeclaringType, field));
}
- public bool Equals(IXamlIlProperty other) =>
- other is XamlIlAvaloniaProperty p && p.AvaloniaProperty.Equals(AvaloniaProperty);
+ abstract class AvaloniaPropertyCustomSetter : IXamlIlPropertySetter
+ {
+ protected AvaloniaXamlIlWellKnownTypes Types;
+ protected IXamlIlField AvaloniaProperty;
- public string Name => _original.Name;
- public IXamlIlType PropertyType => _original.PropertyType;
- public IXamlIlMethod Setter => _original.Setter;
- public IXamlIlMethod Getter => _original.Getter;
- public IReadOnlyList CustomAttributes => _original.CustomAttributes;
+ public AvaloniaPropertyCustomSetter(AvaloniaXamlIlWellKnownTypes types,
+ IXamlIlType declaringType,
+ IXamlIlField avaloniaProperty)
+ {
+ Types = types;
+ AvaloniaProperty = avaloniaProperty;
+ TargetType = declaringType;
+ }
+
+ public IXamlIlType TargetType { get; }
+
+ public PropertySetterBinderParameters BinderParameters { get; } = new PropertySetterBinderParameters
+ {
+ AllowNull = false
+ };
+
+ public IReadOnlyList Parameters { get; set; }
+ public abstract void Emit(IXamlIlEmitter codegen);
+ }
+
+ class BindingSetter : AvaloniaPropertyCustomSetter
+ {
+ public BindingSetter(AvaloniaXamlIlWellKnownTypes types,
+ IXamlIlType declaringType,
+ IXamlIlField avaloniaProperty) : base(types, declaringType, avaloniaProperty)
+ {
+ Parameters = new[] {types.IBinding};
+ }
+
+ public override void Emit(IXamlIlEmitter emitter)
+ {
+ using (var bloc = emitter.LocalsPool.GetLocal(Types.IBinding))
+ emitter
+ .Stloc(bloc.Local)
+ .Ldsfld(AvaloniaProperty)
+ .Ldloc(bloc.Local)
+ // TODO: provide anchor?
+ .Ldnull();
+ emitter.EmitCall(Types.AvaloniaObjectBindMethod, true);
+ }
+ }
+
+ class UnsetValueSetter : AvaloniaPropertyCustomSetter
+ {
+ public UnsetValueSetter(AvaloniaXamlIlWellKnownTypes types, IXamlIlType declaringType, IXamlIlField avaloniaProperty)
+ : base(types, declaringType, avaloniaProperty)
+ {
+ Parameters = new[] {types.UnsetValueType};
+ }
+
+ public override void Emit(IXamlIlEmitter codegen)
+ {
+ var unsetValue = Types.AvaloniaProperty.Fields.First(f => f.Name == "UnsetValue");
+ codegen
+ // Ignore the instance and load one from the static field to avoid extra local variable
+ .Pop()
+ .Ldsfld(AvaloniaProperty)
+ .Ldsfld(unsetValue)
+ .Ldc_I4(0)
+ .EmitCall(Types.AvaloniaObjectSetValueMethod, true);
+ }
+ }
}
}
diff --git a/src/Markup/Avalonia.Markup.Xaml/XamlIl/xamlil.github b/src/Markup/Avalonia.Markup.Xaml/XamlIl/xamlil.github
index c0da3c4981..56c401c48f 160000
--- a/src/Markup/Avalonia.Markup.Xaml/XamlIl/xamlil.github
+++ b/src/Markup/Avalonia.Markup.Xaml/XamlIl/xamlil.github
@@ -1 +1 @@
-Subproject commit c0da3c49810316a96b47a00a83ae79d4f28406a1
+Subproject commit 56c401c48f51979201ad810c96a9644705d4ddd9