10 changed files with 231 additions and 101 deletions
@ -1,21 +0,0 @@ |
|||
using System.Linq; |
|||
using XamlIl.Transform; |
|||
using XamlIl.TypeSystem; |
|||
|
|||
namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions |
|||
{ |
|||
public class AvaloniaPropertyDescriptorEmitter |
|||
{ |
|||
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); |
|||
if (found == null) |
|||
return false; |
|||
|
|||
emitter.Ldsfld(found); |
|||
return true; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,65 @@ |
|||
using System.Linq; |
|||
using XamlIl.Ast; |
|||
using XamlIl.Transform; |
|||
using XamlIl.TypeSystem; |
|||
|
|||
namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers |
|||
{ |
|||
class AvaloniaXamlIlControlTemplateTargetTypeMetadataTransformer : IXamlIlAstTransformer |
|||
{ |
|||
public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node) |
|||
{ |
|||
if (!(node is XamlIlAstObjectNode on |
|||
&& on.Type.GetClrType().FullName == "Avalonia.Markup.Xaml.Templates.ControlTemplate")) |
|||
return node; |
|||
var tt = on.Children.OfType<XamlIlAstXamlPropertyValueNode>().FirstOrDefault(ch => |
|||
ch.Property.GetClrProperty().Name == "TargetType"); |
|||
|
|||
if (context.ParentNodes().FirstOrDefault() is AvaloniaXamlIlTargetTypeMetadataNode) |
|||
// Deja vu. I've just been in this place before
|
|||
return node; |
|||
|
|||
IXamlIlAstTypeReference targetType; |
|||
|
|||
if ((tt?.Values.FirstOrDefault() is XamlIlTypeExtensionNode tn)) |
|||
{ |
|||
targetType = tn.Type; |
|||
} |
|||
else |
|||
{ |
|||
var parentScope = context.ParentNodes().OfType<AvaloniaXamlIlTargetTypeMetadataNode>() |
|||
.FirstOrDefault(); |
|||
if (parentScope?.Type == AvaloniaXamlIlTargetTypeMetadataNode.ScopeType.Style) |
|||
targetType = parentScope.TargetType; |
|||
else |
|||
targetType = new XamlIlAstClrTypeReference(node, |
|||
context.Configuration.TypeSystem.GetType("Avalonia.Controls.Control")); |
|||
} |
|||
|
|||
|
|||
|
|||
return new AvaloniaXamlIlTargetTypeMetadataNode(on, targetType, |
|||
AvaloniaXamlIlTargetTypeMetadataNode.ScopeType.ControlTemplate); |
|||
} |
|||
} |
|||
|
|||
class AvaloniaXamlIlTargetTypeMetadataNode : XamlIlValueWithSideEffectNodeBase |
|||
{ |
|||
public IXamlIlAstTypeReference TargetType { get; set; } |
|||
public ScopeType Type { get; } |
|||
|
|||
public enum ScopeType |
|||
{ |
|||
Style, |
|||
ControlTemplate |
|||
} |
|||
|
|||
public AvaloniaXamlIlTargetTypeMetadataNode(IXamlIlAstValueNode value, IXamlIlAstTypeReference targetType, |
|||
ScopeType type) |
|||
: base(value, value) |
|||
{ |
|||
TargetType = targetType; |
|||
Type = type; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
using System.Linq; |
|||
using XamlIl.Ast; |
|||
using XamlIl.Transform; |
|||
|
|||
namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers |
|||
{ |
|||
public class AvaloniaXamlIlMetadataRemover : IXamlIlAstTransformer |
|||
{ |
|||
public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node) |
|||
{ |
|||
if (node is AvaloniaXamlIlTargetTypeMetadataNode md) |
|||
return md.Value; |
|||
|
|||
return node; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,79 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using Avalonia.Markup.Xaml.Parsers; |
|||
using Avalonia.Utilities; |
|||
using XamlIl; |
|||
using XamlIl.Ast; |
|||
using XamlIl.Transform; |
|||
using XamlIl.Transform.Transformers; |
|||
using XamlIl.TypeSystem; |
|||
|
|||
namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions |
|||
{ |
|||
class XamlIlAvaloniaPropertyHelper |
|||
{ |
|||
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); |
|||
if (found == null) |
|||
return false; |
|||
|
|||
emitter.Ldsfld(found); |
|||
return true; |
|||
} |
|||
|
|||
public static XamlIlAvaloniaPropertyNode CreateNode(XamlIlAstTransformationContext context, |
|||
string propertyName, IXamlIlAstTypeReference selectorTypeReference, IXamlIlLineInfo lineInfo) |
|||
{ |
|||
XamlIlAstNamePropertyReference forgedReference; |
|||
|
|||
var parser = new PropertyParser(); |
|||
|
|||
var parsedPropertyName = parser.Parse(new CharacterReader(propertyName.AsSpan())); |
|||
if(parsedPropertyName.owner == null) |
|||
forgedReference = new XamlIlAstNamePropertyReference(lineInfo, selectorTypeReference, |
|||
propertyName, selectorTypeReference); |
|||
else |
|||
{ |
|||
var xmlOwner = parsedPropertyName.ns; |
|||
if (xmlOwner != null) |
|||
xmlOwner += ":"; |
|||
xmlOwner += parsedPropertyName.owner; |
|||
|
|||
var t = XamlIlTypeReferenceResolver.ResolveType(context, xmlOwner, lineInfo, true); |
|||
var tref = new XamlIlAstClrTypeReference(lineInfo, t); |
|||
forgedReference = new XamlIlAstNamePropertyReference(lineInfo, |
|||
tref, parsedPropertyName.name, tref); |
|||
} |
|||
|
|||
var clrProperty = |
|||
((XamlIlAstClrPropertyReference)new XamlIlPropertyReferenceResolver().Transform(context, |
|||
forgedReference)).Property; |
|||
return new XamlIlAvaloniaPropertyNode(lineInfo, |
|||
context.Configuration.TypeSystem.GetType("Avalonia.AvaloniaProperty"), |
|||
clrProperty); |
|||
} |
|||
} |
|||
|
|||
class XamlIlAvaloniaPropertyNode : XamlIlAstNode, IXamlIlAstValueNode, IXamlIlAstEmitableNode |
|||
{ |
|||
public XamlIlAvaloniaPropertyNode(IXamlIlLineInfo lineInfo, IXamlIlType type, IXamlIlProperty property) : base(lineInfo) |
|||
{ |
|||
Type = new XamlIlAstClrTypeReference(this, type); |
|||
Property = property; |
|||
} |
|||
|
|||
public IXamlIlProperty Property { get; } |
|||
|
|||
public IXamlIlAstTypeReference Type { get; } |
|||
public XamlIlNodeEmitResult Emit(XamlIlEmitContext context, IXamlIlEmitter codeGen) |
|||
{ |
|||
if (!XamlIlAvaloniaPropertyHelper.Emit(context, codeGen, Property)) |
|||
throw new XamlIlLoadException(Property.Name + " is not an AvaloniaProperty", this); |
|||
return XamlIlNodeEmitResult.Type(0, Type.GetClrType()); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue