Browse Source

Update Avalonia to renamed XamlX branch.

pull/4223/head
Jeremy Koritzinsky 6 years ago
parent
commit
8c41ab4db6
  1. 6
      src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj
  2. 2
      src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.Helpers.cs
  3. 47
      src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
  4. 4
      src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
  5. 36
      src/Markup/Avalonia.Markup.Xaml/XamlIl/AvaloniaXamlIlRuntimeCompiler.cs
  6. 75
      src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlCompiler.cs
  7. 78
      src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlLanguage.cs
  8. 98
      src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AddNameScopeRegistration.cs
  9. 10
      src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaBindingExtensionHackTransformer.cs
  10. 10
      src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlAvaloniaPropertyResolver.cs
  11. 28
      src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlConstructorServiceProviderTransformer.cs
  12. 28
      src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlControlTemplateTargetTypeMetadataTransformer.cs
  13. 26
      src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlDesignPropertiesTransformer.cs
  14. 8
      src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlMetadataRemover.cs
  15. 118
      src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlSelectorTransformer.cs
  16. 68
      src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlSetterTransformer.cs
  17. 78
      src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlTransformInstanceAttachedProperties.cs
  18. 12
      src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlTransitionsTypeMetadataTransformer.cs
  19. 96
      src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs
  20. 14
      src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/IgnoredDirectivesTransformer.cs
  21. 19
      src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/XNameTransformer.cs
  22. 103
      src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/XamlIlAvaloniaPropertyHelper.cs
  23. 2
      src/Markup/Avalonia.Markup.Xaml/XamlIl/xamlil.github

6
src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj

@ -21,10 +21,10 @@
<Link>XamlIlExtensions/%(RecursiveDir)%(FileName)%(Extension)</Link>
</Compile>
<Compile Remove="external/cecil/**/*.*" />
<Compile Include="../Markup/Avalonia.Markup.Xaml/XamlIl\xamlil.github\src\XamlIl\**\*.cs">
<Compile Include="../Markup/Avalonia.Markup.Xaml/XamlIl\xamlil.github\src\XamlX\**\*.cs">
<Link>XamlIl/%(RecursiveDir)%(FileName)%(Extension)</Link>
</Compile>
<Compile Include="../Markup/Avalonia.Markup.Xaml/XamlIl\xamlil.github\src\XamlIl.Cecil\**\*.cs">
<Compile Include="../Markup/Avalonia.Markup.Xaml/XamlIl\xamlil.github\src\XamlX.IL.Cecil\**\*.cs">
<Link>XamlIl.Cecil/%(RecursiveDir)%(FileName)%(Extension)</Link>
</Compile>
<Compile Include="../Markup/Avalonia.Markup\Markup\Parsers\SelectorGrammar.cs">
@ -44,7 +44,7 @@
</Compile>
<Compile Remove="../Markup/Avalonia.Markup.Xaml/XamlIl\xamlil.github\**\obj\**\*.cs" />
<Compile Remove="../Markup/Avalonia.Markup.Xaml/XamlIl\xamlil.github\src\XamlIl\TypeSystem\SreTypeSystem.cs" />
<Compile Remove="../Markup/Avalonia.Markup.Xaml/XamlIl\xamlil.github\src\XamlX\IL\SreTypeSystem.cs" />
<PackageReference Include="Avalonia.Unofficial.Cecil" Version="20190417.2.0" PrivateAssets="All" />
<PackageReference Condition="$(TargetFramework) == 'netstandard2.0'" Include="ILRepack.MSBuild.Task" Version="2.0.13" PrivateAssets="All" />
<PackageReference Include="Microsoft.Build.Framework" Version="15.1.548" PrivateAssets="All" />

2
src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.Helpers.cs

@ -5,7 +5,7 @@ using Avalonia.Utilities;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Collections.Generic;
using XamlIl.TypeSystem;
using XamlX.TypeSystem;
namespace Avalonia.Build.Tasks
{

47
src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs

@ -7,17 +7,18 @@ using System.Text;
using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions;
using Microsoft.Build.Framework;
using Mono.Cecil;
using XamlIl.TypeSystem;
using Avalonia.Utilities;
using Mono.Cecil.Cil;
using Mono.Cecil.Rocks;
using XamlIl;
using XamlIl.Ast;
using XamlIl.Parsers;
using XamlIl.Transform;
using XamlX;
using XamlX.Ast;
using XamlX.Parsers;
using XamlX.Transform;
using XamlX.TypeSystem;
using FieldAttributes = Mono.Cecil.FieldAttributes;
using MethodAttributes = Mono.Cecil.MethodAttributes;
using TypeAttributes = Mono.Cecil.TypeAttributes;
using XamlX.IL;
namespace Avalonia.Build.Tasks
{
@ -51,11 +52,11 @@ namespace Avalonia.Build.Tasks
// Nothing to do
return new CompileResult(true);
var xamlLanguage = AvaloniaXamlIlLanguage.Configure(typeSystem);
var compilerConfig = new XamlIlTransformerConfiguration(typeSystem,
var (xamlLanguage , emitConfig) = AvaloniaXamlIlLanguage.Configure(typeSystem);
var compilerConfig = new TransformerConfiguration(typeSystem,
typeSystem.TargetAssembly,
xamlLanguage,
XamlIlXmlnsMappings.Resolve(typeSystem, xamlLanguage),
XamlXmlnsMappings.Resolve(typeSystem, xamlLanguage),
AvaloniaXamlIlLanguage.CustomValueConverter);
@ -63,10 +64,10 @@ namespace Avalonia.Build.Tasks
TypeAttributes.Class, asm.MainModule.TypeSystem.Object);
asm.MainModule.Types.Add(contextDef);
var contextClass = XamlIlContextDefinition.GenerateContextClass(typeSystem.CreateTypeBuilder(contextDef), typeSystem,
xamlLanguage);
var contextClass = XamlILContextDefinition.GenerateContextClass(typeSystem.CreateTypeBuilder(contextDef), typeSystem,
xamlLanguage, emitConfig);
var compiler = new AvaloniaXamlIlCompiler(compilerConfig, contextClass) { EnableIlVerification = verifyIl };
var compiler = new AvaloniaXamlIlCompiler(compilerConfig, emitConfig, contextClass) { EnableIlVerification = verifyIl };
var editorBrowsableAttribute = typeSystem
.GetTypeReference(typeSystem.FindType("System.ComponentModel.EditorBrowsableAttribute"))
@ -126,35 +127,35 @@ namespace Avalonia.Build.Tasks
// StreamReader is needed here to handle BOM
var xaml = new StreamReader(new MemoryStream(res.FileContents)).ReadToEnd();
var parsed = XDocumentXamlIlParser.Parse(xaml);
var parsed = XDocumentXamlParser.Parse(xaml);
var initialRoot = (XamlIlAstObjectNode)parsed.Root;
var initialRoot = (XamlAstObjectNode)parsed.Root;
var precompileDirective = initialRoot.Children.OfType<XamlIlAstXmlDirective>()
var precompileDirective = initialRoot.Children.OfType<XamlAstXmlDirective>()
.FirstOrDefault(d => d.Namespace == XamlNamespaces.Xaml2006 && d.Name == "Precompile");
if (precompileDirective != null)
{
var precompileText = (precompileDirective.Values[0] as XamlIlAstTextNode)?.Text.Trim()
var precompileText = (precompileDirective.Values[0] as XamlAstTextNode)?.Text.Trim()
.ToLowerInvariant();
if (precompileText == "false")
continue;
if (precompileText != "true")
throw new XamlIlParseException("Invalid value for x:Precompile", precompileDirective);
throw new XamlParseException("Invalid value for x:Precompile", precompileDirective);
}
var classDirective = initialRoot.Children.OfType<XamlIlAstXmlDirective>()
var classDirective = initialRoot.Children.OfType<XamlAstXmlDirective>()
.FirstOrDefault(d => d.Namespace == XamlNamespaces.Xaml2006 && d.Name == "Class");
IXamlIlType classType = null;
IXamlType classType = null;
if (classDirective != null)
{
if (classDirective.Values.Count != 1 || !(classDirective.Values[0] is XamlIlAstTextNode tn))
throw new XamlIlParseException("x:Class should have a string value", classDirective);
if (classDirective.Values.Count != 1 || !(classDirective.Values[0] is XamlAstTextNode tn))
throw new XamlParseException("x:Class should have a string value", classDirective);
classType = typeSystem.TargetAssembly.FindType(tn.Text);
if (classType == null)
throw new XamlIlParseException($"Unable to find type `{tn.Text}`", classDirective);
throw new XamlParseException($"Unable to find type `{tn.Text}`", classDirective);
compiler.OverrideRootType(parsed,
new XamlIlAstClrTypeReference(classDirective, classType, false));
new XamlAstClrTypeReference(classDirective, classType, false));
initialRoot.Children.Remove(classDirective);
}
@ -323,7 +324,7 @@ namespace Avalonia.Build.Tasks
catch (Exception e)
{
int lineNumber = 0, linePosition = 0;
if (e is XamlIlParseException xe)
if (e is XamlParseException xe)
{
lineNumber = xe.LineNumber;
linePosition = xe.LinePosition;

4
src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj

@ -58,8 +58,8 @@
<Compile Include="XamlIl\Runtime\IAvaloniaXamlIlXmlNamespaceInfoProviderV1.cs" />
<Compile Include="XamlIl\Runtime\XamlIlRuntimeHelpers.cs" />
<Compile Include="XamlLoadException.cs" />
<Compile Include="XamlIl\xamlil.github\src\XamlIl\**\*.cs" />
<Compile Condition="$(UseCecil) == true" Include="XamlIl\xamlil.github\src\XamlIl.Cecil\**\*.cs" />
<Compile Include="XamlIl\xamlil.github\src\XamlX\**\*.cs" />
<Compile Condition="$(UseCecil) == true" Include="XamlIl\xamlil.github\src\XamlX.Il.Cecil\**\*.cs" />
<Compile Remove="XamlIl\xamlil.github\**\obj\**\*.cs" />
<Compile Include="..\Avalonia.Markup\Markup\Parsers\SelectorGrammar.cs" />
<Compile Include="XamlTypes.cs" />

36
src/Markup/Avalonia.Markup.Xaml/XamlIl/AvaloniaXamlIlRuntimeCompiler.cs

@ -10,12 +10,15 @@ using System.Runtime.InteropServices;
using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions;
using Avalonia.Markup.Xaml.XamlIl.Runtime;
using Avalonia.Platform;
using XamlIl.Transform;
using XamlIl.TypeSystem;
using XamlX.Transform;
using XamlX.TypeSystem;
using XamlX.IL;
using XamlX.Emit;
#if RUNTIME_XAML_CECIL
using TypeAttributes = Mono.Cecil.TypeAttributes;
using Mono.Cecil;
using XamlIl.Ast;
using XamlX.Ast;
using XamlX.IL.Cecil;
#endif
namespace Avalonia.Markup.Xaml.XamlIl
{
@ -24,9 +27,10 @@ namespace Avalonia.Markup.Xaml.XamlIl
#if !RUNTIME_XAML_CECIL
private static SreTypeSystem _sreTypeSystem;
private static ModuleBuilder _sreBuilder;
private static IXamlIlType _sreContextType;
private static XamlIlLanguageTypeMappings _sreMappings;
private static XamlIlXmlnsMappings _sreXmlns;
private static IXamlType _sreContextType;
private static XamlLanguageTypeMappings _sreMappings;
private static XamlLanguageEmitMappings<IXamlILEmitter, XamlILNodeEmitResult> _sreEmitMappings;
private static XamlXmlnsMappings _sreXmlns;
private static AssemblyBuilder _sreAsm;
private static bool _sreCanSave;
@ -82,13 +86,14 @@ namespace Avalonia.Markup.Xaml.XamlIl
}
if (_sreMappings == null)
_sreMappings = AvaloniaXamlIlLanguage.Configure(_sreTypeSystem);
(_sreMappings, _sreEmitMappings) = AvaloniaXamlIlLanguage.Configure(_sreTypeSystem);
if (_sreXmlns == null)
_sreXmlns = XamlIlXmlnsMappings.Resolve(_sreTypeSystem, _sreMappings);
_sreXmlns = XamlXmlnsMappings.Resolve(_sreTypeSystem, _sreMappings);
if (_sreContextType == null)
_sreContextType = XamlIlContextDefinition.GenerateContextClass(
_sreContextType = XamlILContextDefinition.GenerateContextClass(
_sreTypeSystem.CreateTypeBuilder(
_sreBuilder.DefineType("XamlIlContext")), _sreTypeSystem, _sreMappings);
_sreBuilder.DefineType("XamlIlContext")), _sreTypeSystem, _sreMappings,
_sreEmitMappings);
}
@ -115,12 +120,13 @@ namespace Avalonia.Markup.Xaml.XamlIl
InitializeSre();
var asm = localAssembly == null ? null : _sreTypeSystem.GetAssembly(localAssembly);
var compiler = new AvaloniaXamlIlCompiler(new XamlIlTransformerConfiguration(_sreTypeSystem, asm,
var compiler = new AvaloniaXamlIlCompiler(new TransformerConfiguration(_sreTypeSystem, asm,
_sreMappings, _sreXmlns, AvaloniaXamlIlLanguage.CustomValueConverter),
_sreEmitMappings,
_sreContextType) { EnableIlVerification = true };
var tb = _sreBuilder.DefineType("Builder_" + Guid.NewGuid().ToString("N") + "_" + uri);
IXamlIlType overrideType = null;
IXamlType overrideType = null;
if (rootInstance != null)
{
overrideType = _sreTypeSystem.GetType(rootInstance.GetType());
@ -203,6 +209,7 @@ namespace Avalonia.Markup.Xaml.XamlIl
private static string _cecilEmitDir;
private static CecilTypeSystem _cecilTypeSystem;
private static XamlIlLanguageTypeMappings _cecilMappings;
private static XamlLanguageEmitMappings<IXamlILEmitter, XamlILNodeEmitResult> _cecilEmitMappings;
private static XamlIlXmlnsMappings _cecilXmlns;
private static bool _cecilInitialized;
@ -215,7 +222,7 @@ namespace Avalonia.Markup.Xaml.XamlIl
Directory.CreateDirectory(_cecilEmitDir);
var refs = new[] {path}.Concat(File.ReadAllLines(path + ".refs"));
_cecilTypeSystem = new CecilTypeSystem(refs);
_cecilMappings = AvaloniaXamlIlLanguage.Configure(_cecilTypeSystem);
(_cecilMappings, _cecilEmitMappings) = AvaloniaXamlIlLanguage.Configure(_cecilTypeSystem);
_cecilXmlns = XamlIlXmlnsMappings.Resolve(_cecilTypeSystem, _cecilMappings);
_cecilInitialized = true;
}
@ -226,7 +233,7 @@ namespace Avalonia.Markup.Xaml.XamlIl
if (uri == null)
throw new InvalidOperationException("Please, go away");
InitializeCecil();
IXamlIlType overrideType = null;
IXamlType overrideType = null;
if (rootInstance != null)
{
overrideType = _cecilTypeSystem.GetType(rootInstance.GetType().FullName);
@ -261,6 +268,7 @@ namespace Avalonia.Markup.Xaml.XamlIl
localAssembly == null ? null : _cecilTypeSystem.FindAssembly(localAssembly.GetName().Name),
_cecilMappings, XamlIlXmlnsMappings.Resolve(_cecilTypeSystem, _cecilMappings),
AvaloniaXamlIlLanguage.CustomValueConverter),
_cecilEmitMappings,
_cecilTypeSystem.CreateTypeBuilder(contextDef));
compiler.ParseAndCompile(xaml, uri.ToString(), tb, overrideType);
var asmPath = Path.Combine(_cecilEmitDir, safeUri + ".dll");

75
src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlCompiler.cs

@ -1,29 +1,32 @@
using System.Collections.Generic;
using System.Linq;
using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers;
using XamlIl;
using XamlIl.Ast;
using XamlIl.Parsers;
using XamlIl.Transform;
using XamlIl.Transform.Transformers;
using XamlIl.TypeSystem;
using XamlX;
using XamlX.Ast;
using XamlX.Emit;
using XamlX.IL;
using XamlX.Parsers;
using XamlX.Transform;
using XamlX.Transform.Transformers;
using XamlX.TypeSystem;
namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
{
class AvaloniaXamlIlCompiler : XamlIlCompiler
class AvaloniaXamlIlCompiler : XamlILCompiler
{
private readonly XamlIlTransformerConfiguration _configuration;
private readonly IXamlIlType _contextType;
private readonly TransformerConfiguration _configuration;
private readonly IXamlType _contextType;
private readonly AvaloniaXamlIlDesignPropertiesTransformer _designTransformer;
private AvaloniaXamlIlCompiler(XamlIlTransformerConfiguration configuration) : base(configuration, true)
private AvaloniaXamlIlCompiler(TransformerConfiguration configuration, XamlLanguageEmitMappings<IXamlILEmitter, XamlILNodeEmitResult> emitMappings)
: base(configuration, emitMappings, true)
{
_configuration = configuration;
void InsertAfter<T>(params IXamlIlAstTransformer[] t)
void InsertAfter<T>(params IXamlAstTransformer[] t)
=> Transformers.InsertRange(Transformers.FindIndex(x => x is T) + 1, t);
void InsertBefore<T>(params IXamlIlAstTransformer[] t)
void InsertBefore<T>(params IXamlAstTransformer[] t)
=> Transformers.InsertRange(Transformers.FindIndex(x => x is T), t);
@ -37,12 +40,12 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
// Targeted
InsertBefore<XamlIlPropertyReferenceResolver>(new AvaloniaXamlIlTransformInstanceAttachedProperties());
InsertAfter<XamlIlPropertyReferenceResolver>(new AvaloniaXamlIlAvaloniaPropertyResolver());
InsertBefore<PropertyReferenceResolver>(new AvaloniaXamlIlTransformInstanceAttachedProperties());
InsertAfter<PropertyReferenceResolver>(new AvaloniaXamlIlAvaloniaPropertyResolver());
InsertBefore<XamlIlContentConvertTransformer>(
InsertBefore<ContentConvertTransformer>(
new AvaloniaXamlIlSelectorTransformer(),
new AvaloniaXamlIlSetterTransformer(),
new AvaloniaXamlIlControlTemplateTargetTypeMetadataTransformer(),
@ -55,17 +58,21 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
Transformers.Add(new AddNameScopeRegistration());
Transformers.Add(new AvaloniaXamlIlMetadataRemover());
Emitters.Add(new AvaloniaNameScopeRegistrationXamlIlNodeEmitter());
}
public AvaloniaXamlIlCompiler(XamlIlTransformerConfiguration configuration,
IXamlIlTypeBuilder contextTypeBuilder) : this(configuration)
public AvaloniaXamlIlCompiler(TransformerConfiguration configuration,
XamlLanguageEmitMappings<IXamlILEmitter, XamlILNodeEmitResult> emitMappings,
IXamlTypeBuilder<IXamlILEmitter> contextTypeBuilder)
: this(configuration, emitMappings)
{
_contextType = CreateContextType(contextTypeBuilder);
}
public AvaloniaXamlIlCompiler(XamlIlTransformerConfiguration configuration,
IXamlIlType contextType) : this(configuration)
public AvaloniaXamlIlCompiler(TransformerConfiguration configuration,
XamlLanguageEmitMappings<IXamlILEmitter, XamlILNodeEmitResult> emitMappings,
IXamlType contextType) : this(configuration, emitMappings)
{
_contextType = contextType;
}
@ -79,37 +86,35 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
set => _designTransformer.IsDesignMode = value;
}
public void ParseAndCompile(string xaml, string baseUri, IFileSource fileSource, IXamlIlTypeBuilder tb, IXamlIlType overrideRootType)
public void ParseAndCompile(string xaml, string baseUri, IFileSource fileSource, IXamlTypeBuilder<IXamlILEmitter> tb, IXamlType overrideRootType)
{
var parsed = XDocumentXamlIlParser.Parse(xaml, new Dictionary<string, string>
var parsed = XDocumentXamlParser.Parse(xaml, new Dictionary<string, string>
{
{XamlNamespaces.Blend2008, XamlNamespaces.Blend2008}
});
var rootObject = (XamlIlAstObjectNode)parsed.Root;
var rootObject = (XamlAstObjectNode)parsed.Root;
var classDirective = rootObject.Children
.OfType<XamlIlAstXmlDirective>().FirstOrDefault(x =>
.OfType<XamlAstXmlDirective>().FirstOrDefault(x =>
x.Namespace == XamlNamespaces.Xaml2006
&& x.Name == "Class");
var rootType =
classDirective != null ?
new XamlIlAstClrTypeReference(classDirective,
_configuration.TypeSystem.GetType(((XamlIlAstTextNode)classDirective.Values[0]).Text),
new XamlAstClrTypeReference(classDirective,
_configuration.TypeSystem.GetType(((XamlAstTextNode)classDirective.Values[0]).Text),
false) :
XamlIlTypeReferenceResolver.ResolveType(CreateTransformationContext(parsed, true),
(XamlIlAstXmlTypeReference)rootObject.Type, true);
TypeReferenceResolver.ResolveType(CreateTransformationContext(parsed, true),
(XamlAstXmlTypeReference)rootObject.Type, true);
if (overrideRootType != null)
{
if (!rootType.Type.IsAssignableFrom(overrideRootType))
throw new XamlIlLoadException(
throw new XamlX.XamlLoadException(
$"Unable to substitute {rootType.Type.GetFqn()} with {overrideRootType.GetFqn()}", rootObject);
rootType = new XamlIlAstClrTypeReference(rootObject, overrideRootType, false);
rootType = new XamlAstClrTypeReference(rootObject, overrideRootType, false);
}
OverrideRootType(parsed, rootType);
@ -119,17 +124,17 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
}
public void OverrideRootType(XamlIlDocument doc, IXamlIlAstTypeReference newType)
public void OverrideRootType(XamlDocument doc, IXamlAstTypeReference newType)
{
var root = (XamlIlAstObjectNode)doc.Root;
var root = (XamlAstObjectNode)doc.Root;
var oldType = root.Type;
if (oldType.Equals(newType))
return;
root.Type = newType;
foreach (var child in root.Children.OfType<XamlIlAstXamlPropertyValueNode>())
foreach (var child in root.Children.OfType<XamlAstXamlPropertyValueNode>())
{
if (child.Property is XamlIlAstNamePropertyReference prop)
if (child.Property is XamlAstNamePropertyReference prop)
{
if (prop.DeclaringType.Equals(oldType))
prop.DeclaringType = newType;

78
src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlLanguage.cs

@ -2,10 +2,12 @@ using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers;
using XamlIl;
using XamlIl.Ast;
using XamlIl.Transform;
using XamlIl.TypeSystem;
using XamlX;
using XamlX.Ast;
using XamlX.Emit;
using XamlX.IL;
using XamlX.Transform;
using XamlX.TypeSystem;
namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
{
@ -17,12 +19,12 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
class AvaloniaXamlIlLanguage
{
public static XamlIlLanguageTypeMappings Configure(IXamlIlTypeSystem typeSystem)
public static (XamlLanguageTypeMappings language, XamlLanguageEmitMappings<IXamlILEmitter, XamlILNodeEmitResult> emit) Configure(IXamlTypeSystem typeSystem)
{
var runtimeHelpers = typeSystem.GetType("Avalonia.Markup.Xaml.XamlIl.Runtime.XamlIlRuntimeHelpers");
var assignBindingAttribute = typeSystem.GetType("Avalonia.Data.AssignBindingAttribute");
var bindingType = typeSystem.GetType("Avalonia.Data.IBinding");
var rv = new XamlIlLanguageTypeMappings(typeSystem)
var rv = new XamlLanguageTypeMappings(typeSystem)
{
SupportInitialize = typeSystem.GetType("System.ComponentModel.ISupportInitialize"),
XmlnsAttributes =
@ -51,18 +53,22 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
},
InnerServiceProviderFactoryMethod =
runtimeHelpers.FindMethod(m => m.Name == "CreateInnerServiceProviderV1"),
ProvideValueTargetPropertyEmitter = XamlIlAvaloniaPropertyHelper.Emit,
};
rv.CustomAttributeResolver = new AttributeResolver(typeSystem, rv);
rv.ContextTypeBuilderCallback = (b, c) => EmitNameScopeField(rv, typeSystem, b, c);
return rv;
var emit = new XamlLanguageEmitMappings<IXamlILEmitter, XamlILNodeEmitResult>
{
ProvideValueTargetPropertyEmitter = XamlIlAvaloniaPropertyHelper.Emit,
ContextTypeBuilderCallback = (b, c) => EmitNameScopeField(rv, typeSystem, b, c)
};
return (rv, emit);
}
public const string ContextNameScopeFieldName = "AvaloniaNameScope";
private static void EmitNameScopeField(XamlIlLanguageTypeMappings mappings,
IXamlIlTypeSystem typeSystem,
IXamlIlTypeBuilder typebuilder, IXamlIlEmitter constructor)
private static void EmitNameScopeField(XamlLanguageTypeMappings mappings,
IXamlTypeSystem typeSystem,
IXamlTypeBuilder<IXamlILEmitter> typebuilder, IXamlILEmitter constructor)
{
var nameScopeType = typeSystem.FindType("Avalonia.Controls.INameScope");
@ -78,23 +84,23 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
}
class AttributeResolver : IXamlIlCustomAttributeResolver
class AttributeResolver : IXamlCustomAttributeResolver
{
private readonly IXamlIlType _typeConverterAttribute;
private readonly IXamlType _typeConverterAttribute;
private readonly List<KeyValuePair<IXamlIlType, IXamlIlType>> _converters =
new List<KeyValuePair<IXamlIlType, IXamlIlType>>();
private readonly List<KeyValuePair<IXamlType, IXamlType>> _converters =
new List<KeyValuePair<IXamlType, IXamlType>>();
private readonly IXamlIlType _avaloniaList;
private readonly IXamlIlType _avaloniaListConverter;
private readonly IXamlType _avaloniaList;
private readonly IXamlType _avaloniaListConverter;
public AttributeResolver(IXamlIlTypeSystem typeSystem, XamlIlLanguageTypeMappings mappings)
public AttributeResolver(IXamlTypeSystem typeSystem, XamlLanguageTypeMappings mappings)
{
_typeConverterAttribute = mappings.TypeConverterAttributes.First();
void AddType(IXamlIlType type, IXamlIlType conv)
=> _converters.Add(new KeyValuePair<IXamlIlType, IXamlIlType>(type, conv));
void AddType(IXamlType type, IXamlType conv)
=> _converters.Add(new KeyValuePair<IXamlType, IXamlType>(type, conv));
void Add(string type, string conv)
=> AddType(typeSystem.GetType(type), typeSystem.GetType(conv));
@ -113,7 +119,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
_avaloniaListConverter = typeSystem.GetType("Avalonia.Collections.AvaloniaListConverter`1");
}
IXamlIlType LookupConverter(IXamlIlType type)
IXamlType LookupConverter(IXamlType type)
{
foreach(var p in _converters)
if (p.Key.Equals(type))
@ -123,15 +129,15 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
return null;
}
class ConstructedAttribute : IXamlIlCustomAttribute
class ConstructedAttribute : IXamlCustomAttribute
{
public bool Equals(IXamlIlCustomAttribute other) => false;
public bool Equals(IXamlCustomAttribute other) => false;
public IXamlIlType Type { get; }
public IXamlType Type { get; }
public List<object> Parameters { get; }
public Dictionary<string, object> Properties { get; }
public ConstructedAttribute(IXamlIlType type, List<object> parameters, Dictionary<string, object> properties)
public ConstructedAttribute(IXamlType type, List<object> parameters, Dictionary<string, object> properties)
{
Type = type;
Parameters = parameters ?? new List<object>();
@ -139,7 +145,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
}
}
public IXamlIlCustomAttribute GetCustomAttribute(IXamlIlType type, IXamlIlType attributeType)
public IXamlCustomAttribute GetCustomAttribute(IXamlType type, IXamlType attributeType)
{
if (attributeType.Equals(_typeConverterAttribute))
{
@ -151,25 +157,25 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
return null;
}
public IXamlIlCustomAttribute GetCustomAttribute(IXamlIlProperty property, IXamlIlType attributeType)
public IXamlCustomAttribute GetCustomAttribute(IXamlProperty property, IXamlType attributeType)
{
return null;
}
}
public static bool CustomValueConverter(XamlIlAstTransformationContext context,
IXamlIlAstValueNode node, IXamlIlType type, out IXamlIlAstValueNode result)
public static bool CustomValueConverter(AstTransformationContext context,
IXamlAstValueNode node, IXamlType type, out IXamlAstValueNode result)
{
if (type.FullName == "System.TimeSpan"
&& node is XamlIlAstTextNode tn
&& node is XamlAstTextNode tn
&& !tn.Text.Contains(":"))
{
var seconds = double.Parse(tn.Text, CultureInfo.InvariantCulture);
result = new XamlIlStaticOrTargetedReturnMethodCallNode(tn,
result = new XamlStaticOrTargetedReturnMethodCallNode(tn,
type.FindMethod("FromSeconds", type, false, context.Configuration.WellKnownTypes.Double),
new[]
{
new XamlIlConstantNode(tn, context.Configuration.WellKnownTypes.Double, seconds)
new XamlConstantNode(tn, context.Configuration.WellKnownTypes.Double, seconds)
});
return true;
}
@ -178,9 +184,9 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
{
var scope = context.ParentNodes().OfType<AvaloniaXamlIlTargetTypeMetadataNode>().FirstOrDefault();
if (scope == null)
throw new XamlIlLoadException("Unable to find the parent scope for AvaloniaProperty lookup", node);
if (!(node is XamlIlAstTextNode text))
throw new XamlIlLoadException("Property should be a text node", node);
throw new XamlX.XamlLoadException("Unable to find the parent scope for AvaloniaProperty lookup", node);
if (!(node is XamlAstTextNode text))
throw new XamlX.XamlLoadException("Property should be a text node", node);
result = XamlIlAvaloniaPropertyHelper.CreateNode(context, text.Text, scope.TargetType, text);
return true;
}

98
src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AddNameScopeRegistration.cs

@ -1,33 +1,35 @@
using System;
using System.Linq;
using XamlIl.Ast;
using XamlIl.Transform;
using XamlIl.TypeSystem;
using XamlX.Ast;
using XamlX.Emit;
using XamlX.IL;
using XamlX.Transform;
using XamlX.TypeSystem;
namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{
class AddNameScopeRegistration : IXamlIlAstTransformer
class AddNameScopeRegistration : IXamlAstTransformer
{
public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node)
public IXamlAstNode Transform(AstTransformationContext context, IXamlAstNode node)
{
if (node is XamlIlPropertyAssignmentNode pa
if (node is XamlPropertyAssignmentNode pa
&& pa.Property.Name == "Name"
&& pa.Property.DeclaringType.FullName == "Avalonia.StyledElement")
{
if (context.ParentNodes().FirstOrDefault() is XamlIlManipulationGroupNode mg
if (context.ParentNodes().FirstOrDefault() is XamlManipulationGroupNode mg
&& mg.Children.OfType<AvaloniaNameScopeRegistrationXamlIlNode>().Any())
return node;
IXamlIlAstValueNode value = null;
IXamlAstValueNode 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))
if (!(value is XamlAstTextNode))
{
var local = new XamlIlAstCompilerLocalNode(value);
var local = new XamlAstCompilerLocalNode(value);
// Wrap original in local initialization
pa.Values[c] = new XamlIlAstLocalInitializationNodeEmitter(value, value, local);
pa.Values[c] = new XamlAstLocalInitializationNodeEmitter(value, value, local);
// Use local
value = local;
}
@ -36,20 +38,20 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
}
if (value != null)
return new XamlIlManipulationGroupNode(pa)
return new XamlManipulationGroupNode(pa)
{
Children =
{
pa,
new AvaloniaNameScopeRegistrationXamlIlNode(value, context.GetAvaloniaTypes())
new AvaloniaNameScopeRegistrationXamlIlNode(value)
}
};
}
if (!context.ParentNodes().Any()
&& node is XamlIlValueWithManipulationNode mnode)
&& node is XamlValueWithManipulationNode mnode)
{
mnode.Manipulation = new XamlIlManipulationGroupNode(mnode,
mnode.Manipulation = new XamlManipulationGroupNode(mnode,
new[]
{
mnode.Manipulation,
@ -59,17 +61,17 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
return node;
}
class HandleRootObjectScopeNode : XamlIlAstNode, IXamlIlAstManipulationNode, IXamlIlAstEmitableNode
class HandleRootObjectScopeNode : XamlAstNode, IXamlAstManipulationNode, IXamlAstEmitableNode<IXamlILEmitter, XamlILNodeEmitResult>
{
private readonly AvaloniaXamlIlWellKnownTypes _types;
public HandleRootObjectScopeNode(IXamlIlLineInfo lineInfo,
public HandleRootObjectScopeNode(IXamlLineInfo lineInfo,
AvaloniaXamlIlWellKnownTypes types) : base(lineInfo)
{
_types = types;
}
public XamlIlNodeEmitResult Emit(XamlIlEmitContext context, IXamlIlEmitter codeGen)
public XamlILNodeEmitResult Emit(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen)
{
var next = codeGen.DefineLabel();
var scopeField = context.RuntimeContext.ContextType.Fields.First(f =>
@ -91,49 +93,55 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
.EmitCall(_types.INameScopeComplete, true);
}
return XamlIlNodeEmitResult.Void(1);
return XamlILNodeEmitResult.Void(1);
}
}
}
class AvaloniaNameScopeRegistrationXamlIlNode : XamlIlAstNode, IXamlIlAstManipulationNode, IXamlIlAstEmitableNode
class AvaloniaNameScopeRegistrationXamlIlNode : XamlAstNode, IXamlAstManipulationNode
{
private readonly AvaloniaXamlIlWellKnownTypes _types;
public IXamlIlAstValueNode Name { get; set; }
public IXamlAstValueNode Name { get; set; }
public AvaloniaNameScopeRegistrationXamlIlNode(IXamlIlAstValueNode name, AvaloniaXamlIlWellKnownTypes types) : base(name)
public AvaloniaNameScopeRegistrationXamlIlNode(IXamlAstValueNode name) : base(name)
{
_types = types;
Name = name;
}
public override void VisitChildren(IXamlIlAstVisitor visitor)
=> Name = (IXamlIlAstValueNode)Name.Visit(visitor);
public override void VisitChildren(IXamlAstVisitor visitor)
=> Name = (IXamlAstValueNode)Name.Visit(visitor);
}
public XamlIlNodeEmitResult Emit(XamlIlEmitContext context, IXamlIlEmitter codeGen)
class AvaloniaNameScopeRegistrationXamlIlNodeEmitter : IXamlAstLocalsNodeEmitter<IXamlILEmitter, XamlILNodeEmitResult>
{
public XamlILNodeEmitResult Emit(IXamlAstNode node, XamlEmitContextWithLocals<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen)
{
var scopeField = context.RuntimeContext.ContextType.Fields.First(f =>
f.Name == AvaloniaXamlIlLanguage.ContextNameScopeFieldName);
using (var targetLoc = context.GetLocal(context.Configuration.WellKnownTypes.Object))
if (node is AvaloniaNameScopeRegistrationXamlIlNode registration)
{
codeGen
// var target = {pop}
.Stloc(targetLoc.Local)
// _context.NameScope.Register(Name, target)
.Ldloc(context.ContextLocal)
.Ldfld(scopeField);
context.Emit(Name, codeGen, Name.Type.GetClrType());
codeGen
.Ldloc(targetLoc.Local)
.EmitCall(_types.INameScopeRegister, true);
}
var scopeField = context.RuntimeContext.ContextType.Fields.First(f =>
f.Name == AvaloniaXamlIlLanguage.ContextNameScopeFieldName);
using (var targetLoc = context.GetLocalOfType(context.Configuration.WellKnownTypes.Object))
{
return XamlIlNodeEmitResult.Void(1);
codeGen
// var target = {pop}
.Stloc(targetLoc.Local)
// _context.NameScope.Register(Name, target)
.Ldloc(context.ContextLocal)
.Ldfld(scopeField);
context.Emit(registration.Name, codeGen, registration.Name.Type.GetClrType());
codeGen
.Ldloc(targetLoc.Local)
.EmitCall(context.GetAvaloniaTypes().INameScopeRegister, true);
}
return XamlILNodeEmitResult.Void(1);
}
return default;
}
}
}

10
src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaBindingExtensionHackTransformer.cs

@ -1,16 +1,16 @@
using XamlIl.Ast;
using XamlIl.Transform;
using XamlX.Ast;
using XamlX.Transform;
namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{
class AvaloniaBindingExtensionHackTransformer : IXamlIlAstTransformer
class AvaloniaBindingExtensionHackTransformer : IXamlAstTransformer
{
public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node)
public IXamlAstNode Transform(AstTransformationContext context, IXamlAstNode node)
{
// Our code base expects XAML parser to prefer `FooExtension` to `Foo` even with `<Foo>` syntax
// This is the legacy of Portable.Xaml, so we emulate that behavior here
if (node is XamlIlAstXmlTypeReference tref
if (node is XamlAstXmlTypeReference tref
&& tref.Name == "Binding"
&& tref.XmlNamespace == "https://github.com/avaloniaui")
tref.IsMarkupExtension = true;

10
src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlAvaloniaPropertyResolver.cs

@ -1,14 +1,14 @@
using System.Linq;
using XamlIl.Ast;
using XamlIl.Transform;
using XamlX.Ast;
using XamlX.Transform;
namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{
class AvaloniaXamlIlAvaloniaPropertyResolver : IXamlIlAstTransformer
class AvaloniaXamlIlAvaloniaPropertyResolver : IXamlAstTransformer
{
public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node)
public IXamlAstNode Transform(AstTransformationContext context, IXamlAstNode node)
{
if (node is XamlIlAstClrProperty prop)
if (node is XamlAstClrProperty prop)
{
var n = prop.Name + "Property";
var field =

28
src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlConstructorServiceProviderTransformer.cs

@ -1,15 +1,17 @@
using System.Linq;
using XamlIl.Ast;
using XamlIl.Transform;
using XamlIl.TypeSystem;
using XamlX.Ast;
using XamlX.Emit;
using XamlX.IL;
using XamlX.Transform;
using XamlX.TypeSystem;
namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{
class AvaloniaXamlIlConstructorServiceProviderTransformer : IXamlIlAstTransformer
class AvaloniaXamlIlConstructorServiceProviderTransformer : IXamlAstTransformer
{
public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node)
public IXamlAstNode Transform(AstTransformationContext context, IXamlAstNode node)
{
if (node is XamlIlAstObjectNode on && on.Arguments.Count == 0)
if (node is XamlAstObjectNode on && on.Arguments.Count == 0)
{
var ctors = on.Type.GetClrType().Constructors;
if (!ctors.Any(c => c.IsPublic && !c.IsStatic && c.Parameters.Count == 0))
@ -27,20 +29,20 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
return node;
}
class InjectServiceProviderNode : XamlIlAstNode, IXamlIlAstValueNode,IXamlIlAstNodeNeedsParentStack,
IXamlIlAstEmitableNode
class InjectServiceProviderNode : XamlAstNode, IXamlAstValueNode,IXamlAstNodeNeedsParentStack,
IXamlAstEmitableNode<IXamlILEmitter, XamlILNodeEmitResult>
{
public InjectServiceProviderNode(IXamlIlType type, IXamlIlLineInfo lineInfo) : base(lineInfo)
public InjectServiceProviderNode(IXamlType type, IXamlLineInfo lineInfo) : base(lineInfo)
{
Type = new XamlIlAstClrTypeReference(lineInfo, type, false);
Type = new XamlAstClrTypeReference(lineInfo, type, false);
}
public IXamlIlAstTypeReference Type { get; }
public IXamlAstTypeReference Type { get; }
public bool NeedsParentStack => true;
public XamlIlNodeEmitResult Emit(XamlIlEmitContext context, IXamlIlEmitter codeGen)
public XamlILNodeEmitResult Emit(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen)
{
codeGen.Ldloc(context.ContextLocal);
return XamlIlNodeEmitResult.Type(0, Type.GetClrType());
return XamlILNodeEmitResult.Type(0, Type.GetClrType());
}
}
}

28
src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlControlTemplateTargetTypeMetadataTransformer.cs

@ -1,29 +1,29 @@
using System.Linq;
using XamlIl.Ast;
using XamlIl.Transform;
using XamlIl.TypeSystem;
using XamlX.Ast;
using XamlX.Transform;
using XamlX.TypeSystem;
namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{
class AvaloniaXamlIlControlTemplateTargetTypeMetadataTransformer : IXamlIlAstTransformer
class AvaloniaXamlIlControlTemplateTargetTypeMetadataTransformer : IXamlAstTransformer
{
public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node)
public IXamlAstNode Transform(AstTransformationContext context, IXamlAstNode node)
{
if (!(node is XamlIlAstObjectNode on
if (!(node is XamlAstObjectNode on
&& on.Type.GetClrType().FullName == "Avalonia.Markup.Xaml.Templates.ControlTemplate"))
return node;
var tt = on.Children.OfType<XamlIlAstXamlPropertyValueNode>().FirstOrDefault(ch =>
var tt = on.Children.OfType<XamlAstXamlPropertyValueNode>().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;
IXamlAstTypeReference targetType;
var templatableBaseType = context.Configuration.TypeSystem.GetType("Avalonia.Controls.Control");
if ((tt?.Values.FirstOrDefault() is XamlIlTypeExtensionNode tn))
if ((tt?.Values.FirstOrDefault() is XamlTypeExtensionNode tn))
{
targetType = tn.Value;
}
@ -33,11 +33,11 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
.FirstOrDefault();
if (parentScope?.ScopeType == AvaloniaXamlIlTargetTypeMetadataNode.ScopeTypes.Style)
targetType = parentScope.TargetType;
else if (context.ParentNodes().Skip(1).FirstOrDefault() is XamlIlAstObjectNode directParentNode
else if (context.ParentNodes().Skip(1).FirstOrDefault() is XamlAstObjectNode directParentNode
&& templatableBaseType.IsAssignableFrom(directParentNode.Type.GetClrType()))
targetType = directParentNode.Type;
else
targetType = new XamlIlAstClrTypeReference(node,
targetType = new XamlAstClrTypeReference(node,
templatableBaseType, false);
}
@ -48,9 +48,9 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
}
}
class AvaloniaXamlIlTargetTypeMetadataNode : XamlIlValueWithSideEffectNodeBase
class AvaloniaXamlIlTargetTypeMetadataNode : XamlValueWithSideEffectNodeBase
{
public IXamlIlAstTypeReference TargetType { get; set; }
public IXamlAstTypeReference TargetType { get; set; }
public ScopeTypes ScopeType { get; }
public enum ScopeTypes
@ -60,7 +60,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
Transitions
}
public AvaloniaXamlIlTargetTypeMetadataNode(IXamlIlAstValueNode value, IXamlIlAstTypeReference targetType,
public AvaloniaXamlIlTargetTypeMetadataNode(IXamlAstValueNode value, IXamlAstTypeReference targetType,
ScopeTypes type)
: base(value, value)
{

26
src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlDesignPropertiesTransformer.cs

@ -1,12 +1,12 @@
using System.Collections.Generic;
using System.Linq;
using XamlIl;
using XamlIl.Ast;
using XamlIl.Transform;
using XamlX;
using XamlX.Ast;
using XamlX.Transform;
namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{
class AvaloniaXamlIlDesignPropertiesTransformer : IXamlIlAstTransformer
class AvaloniaXamlIlDesignPropertiesTransformer : IXamlAstTransformer
{
public bool IsDesignMode { get; set; }
@ -17,14 +17,14 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
};
private const string AvaloniaNs = "https://github.com/avaloniaui";
public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node)
public IXamlAstNode Transform(AstTransformationContext context, IXamlAstNode node)
{
if (node is XamlIlAstObjectNode on)
if (node is XamlAstObjectNode on)
{
for (var c=0; c<on.Children.Count;)
{
var ch = on.Children[c];
if (ch is XamlIlAstXmlDirective directive
if (ch is XamlAstXmlDirective directive
&& directive.Namespace == XamlNamespaces.Blend2008
&& DesignDirectives.TryGetValue(directive.Name, out var mapTo))
{
@ -34,9 +34,9 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
else
{
// Map to an actual property in `Design` class
on.Children[c] = new XamlIlAstXamlPropertyValueNode(ch,
new XamlIlAstNamePropertyReference(ch,
new XamlIlAstXmlTypeReference(ch, AvaloniaNs, "Design"),
on.Children[c] = new XamlAstXamlPropertyValueNode(ch,
new XamlAstNamePropertyReference(ch,
new XamlAstXmlTypeReference(ch, AvaloniaNs, "Design"),
mapTo, on.Type), directive.Values);
c++;
}
@ -44,9 +44,9 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
// Remove all "Design" attached properties in non-design mode
else if (
!IsDesignMode
&& ch is XamlIlAstXamlPropertyValueNode pv
&& pv.Property is XamlIlAstNamePropertyReference pref
&& pref.DeclaringType is XamlIlAstXmlTypeReference dref
&& ch is XamlAstXamlPropertyValueNode pv
&& pv.Property is XamlAstNamePropertyReference pref
&& pref.DeclaringType is XamlAstXmlTypeReference dref
&& dref.XmlNamespace == AvaloniaNs && dref.Name == "Design"
)
{

8
src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlMetadataRemover.cs

@ -1,12 +1,12 @@
using System.Linq;
using XamlIl.Ast;
using XamlIl.Transform;
using XamlX.Ast;
using XamlX.Transform;
namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{
class AvaloniaXamlIlMetadataRemover : IXamlIlAstTransformer
class AvaloniaXamlIlMetadataRemover : IXamlAstTransformer
{
public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node)
public IXamlAstNode Transform(AstTransformationContext context, IXamlAstNode node)
{
if (node is AvaloniaXamlIlTargetTypeMetadataNode md)
return md.Value;

118
src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlSelectorTransformer.cs

@ -3,41 +3,45 @@ using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Avalonia.Markup.Parsers;
using XamlIl;
using XamlIl.Ast;
using XamlIl.Transform;
using XamlIl.Transform.Transformers;
using XamlIl.TypeSystem;
using XamlX;
using XamlX.Ast;
using XamlX.Emit;
using XamlX.IL;
using XamlX.Transform;
using XamlX.Transform.Transformers;
using XamlX.TypeSystem;
namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{
class AvaloniaXamlIlSelectorTransformer : IXamlIlAstTransformer
using XamlParseException = XamlX.XamlParseException;
using XamlLoadException = XamlX.XamlLoadException;
class AvaloniaXamlIlSelectorTransformer : IXamlAstTransformer
{
public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node)
public IXamlAstNode Transform(AstTransformationContext context, IXamlAstNode node)
{
if (!(node is XamlIlAstObjectNode on && on.Type.GetClrType().FullName == "Avalonia.Styling.Style"))
if (!(node is XamlAstObjectNode on && on.Type.GetClrType().FullName == "Avalonia.Styling.Style"))
return node;
var pn = on.Children.OfType<XamlIlAstXamlPropertyValueNode>()
var pn = on.Children.OfType<XamlAstXamlPropertyValueNode>()
.FirstOrDefault(p => p.Property.GetClrProperty().Name == "Selector");
if (pn == null)
return node;
if (pn.Values.Count != 1)
throw new XamlIlParseException("Selector property should should have exactly one value", node);
throw new XamlParseException("Selector property should should have exactly one value", node);
if (pn.Values[0] is XamlIlSelectorNode)
//Deja vu. I've just been in this place before
return node;
if (!(pn.Values[0] is XamlIlAstTextNode tn))
throw new XamlIlParseException("Selector property should be a text node", node);
if (!(pn.Values[0] is XamlAstTextNode tn))
throw new XamlParseException("Selector property should be a text node", node);
var selectorType = pn.Property.GetClrProperty().Getter.ReturnType;
var initialNode = new XamlIlSelectorInitialNode(node, selectorType);
XamlIlSelectorNode Create(IEnumerable<SelectorGrammar.ISyntax> syntax,
Func<string, string, XamlIlAstClrTypeReference> typeResolver)
Func<string, string, XamlAstClrTypeReference> typeResolver)
{
XamlIlSelectorNode result = initialNode;
XamlIlOrSelectorNode results = null;
@ -63,18 +67,18 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
var type = result?.TargetType;
if (type == null)
throw new XamlIlParseException("Property selectors must be applied to a type.", node);
throw new XamlParseException("Property selectors must be applied to a type.", node);
var targetProperty =
type.GetAllProperties().FirstOrDefault(p => p.Name == property.Property);
if (targetProperty == null)
throw new XamlIlParseException($"Cannot find '{property.Property}' on '{type}", node);
throw new XamlParseException($"Cannot find '{property.Property}' on '{type}", node);
if (!XamlIlTransformHelpers.TryGetCorrectlyTypedValue(context,
new XamlIlAstTextNode(node, property.Value, context.Configuration.WellKnownTypes.String),
if (!XamlTransformHelpers.TryGetCorrectlyTypedValue(context,
new XamlAstTextNode(node, property.Value, context.Configuration.WellKnownTypes.String),
targetProperty.PropertyType, out var typedValue))
throw new XamlIlParseException(
throw new XamlParseException(
$"Cannot convert '{property.Value}' to '{targetProperty.PropertyType.GetFqn()}",
node);
@ -100,7 +104,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
result = initialNode;
break;
default:
throw new XamlIlParseException($"Unsupported selector grammar '{i.GetType()}'.", node);
throw new XamlParseException($"Unsupported selector grammar '{i.GetType()}'.", node);
}
}
@ -119,15 +123,15 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
}
catch (Exception e)
{
throw new XamlIlParseException("Unable to parse selector: " + e.Message, node);
throw new XamlParseException("Unable to parse selector: " + e.Message, node);
}
var selector = Create(parsed, (p, n)
=> XamlIlTypeReferenceResolver.ResolveType(context, $"{p}:{n}", true, node, true));
=> TypeReferenceResolver.ResolveType(context, $"{p}:{n}", true, node, true));
pn.Values[0] = selector;
return new AvaloniaXamlIlTargetTypeMetadataNode(on,
new XamlIlAstClrTypeReference(selector, selector.TargetType, false),
new XamlAstClrTypeReference(selector, selector.TargetType, false),
AvaloniaXamlIlTargetTypeMetadataNode.ScopeTypes.Style);
}
@ -135,32 +139,32 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
abstract class XamlIlSelectorNode : XamlIlAstNode, IXamlIlAstValueNode, IXamlIlAstEmitableNode
abstract class XamlIlSelectorNode : XamlAstNode, IXamlAstValueNode, IXamlAstEmitableNode<IXamlILEmitter, XamlILNodeEmitResult>
{
protected XamlIlSelectorNode Previous { get; }
public abstract IXamlIlType TargetType { get; }
public abstract IXamlType TargetType { get; }
public XamlIlSelectorNode(XamlIlSelectorNode previous,
IXamlIlLineInfo info = null,
IXamlIlType selectorType = null) : base(info ?? previous)
IXamlLineInfo info = null,
IXamlType selectorType = null) : base(info ?? previous)
{
Previous = previous;
Type = selectorType == null ? previous.Type : new XamlIlAstClrTypeReference(this, selectorType, false);
Type = selectorType == null ? previous.Type : new XamlAstClrTypeReference(this, selectorType, false);
}
public IXamlIlAstTypeReference Type { get; }
public IXamlAstTypeReference Type { get; }
public virtual XamlIlNodeEmitResult Emit(XamlIlEmitContext context, IXamlIlEmitter codeGen)
public virtual XamlILNodeEmitResult Emit(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen)
{
if (Previous != null)
context.Emit(Previous, codeGen, Type.GetClrType());
DoEmit(context, codeGen);
return XamlIlNodeEmitResult.Type(0, Type.GetClrType());
return XamlILNodeEmitResult.Type(0, Type.GetClrType());
}
protected abstract void DoEmit(XamlIlEmitContext context, IXamlIlEmitter codeGen);
protected abstract void DoEmit(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen);
protected void EmitCall(XamlIlEmitContext context, IXamlIlEmitter codeGen, Func<IXamlIlMethod, bool> method)
protected void EmitCall(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen, Func<IXamlMethod, bool> method)
{
var selectors = context.Configuration.TypeSystem.GetType("Avalonia.Styling.Selectors");
var found = selectors.FindMethod(m => m.IsStatic && m.Parameters.Count > 0 && method(m));
@ -170,27 +174,27 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
class XamlIlSelectorInitialNode : XamlIlSelectorNode
{
public XamlIlSelectorInitialNode(IXamlIlLineInfo info,
IXamlIlType selectorType) : base(null, info, selectorType)
public XamlIlSelectorInitialNode(IXamlLineInfo info,
IXamlType selectorType) : base(null, info, selectorType)
{
}
public override IXamlIlType TargetType => null;
protected override void DoEmit(XamlIlEmitContext context, IXamlIlEmitter codeGen) => codeGen.Ldnull();
public override IXamlType TargetType => null;
protected override void DoEmit(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen) => codeGen.Ldnull();
}
class XamlIlTypeSelector : XamlIlSelectorNode
{
public bool Concrete { get; }
public XamlIlTypeSelector(XamlIlSelectorNode previous, IXamlIlType type, bool concrete) : base(previous)
public XamlIlTypeSelector(XamlIlSelectorNode previous, IXamlType type, bool concrete) : base(previous)
{
TargetType = type;
Concrete = concrete;
}
public override IXamlIlType TargetType { get; }
protected override void DoEmit(XamlIlEmitContext context, IXamlIlEmitter codeGen)
public override IXamlType TargetType { get; }
protected override void DoEmit(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen)
{
var name = Concrete ? "OfType" : "Is";
codeGen.Ldtype(TargetType);
@ -217,8 +221,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
}
public override IXamlIlType TargetType => Previous?.TargetType;
protected override void DoEmit(XamlIlEmitContext context, IXamlIlEmitter codeGen)
public override IXamlType TargetType => Previous?.TargetType;
protected override void DoEmit(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen)
{
codeGen.Ldstr(String);
var name = _type.ToString();
@ -242,8 +246,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
_type = type;
}
public override IXamlIlType TargetType => null;
protected override void DoEmit(XamlIlEmitContext context, IXamlIlEmitter codeGen)
public override IXamlType TargetType => null;
protected override void DoEmit(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen)
{
var name = _type.ToString();
EmitCall(context, codeGen,
@ -260,8 +264,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
Argument = argument;
}
public override IXamlIlType TargetType => Previous?.TargetType;
protected override void DoEmit(XamlIlEmitContext context, IXamlIlEmitter codeGen)
public override IXamlType TargetType => Previous?.TargetType;
protected override void DoEmit(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen)
{
context.Emit(Argument, codeGen, Type.GetClrType());
EmitCall(context, codeGen,
@ -272,22 +276,22 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
class XamlIlPropertyEqualsSelector : XamlIlSelectorNode
{
public XamlIlPropertyEqualsSelector(XamlIlSelectorNode previous,
IXamlIlProperty property,
IXamlIlAstValueNode value)
IXamlProperty property,
IXamlAstValueNode value)
: base(previous)
{
Property = property;
Value = value;
}
public IXamlIlProperty Property { get; set; }
public IXamlIlAstValueNode Value { get; set; }
public IXamlProperty Property { get; set; }
public IXamlAstValueNode Value { get; set; }
public override IXamlIlType TargetType => Previous?.TargetType;
protected override void DoEmit(XamlIlEmitContext context, IXamlIlEmitter codeGen)
public override IXamlType TargetType => Previous?.TargetType;
protected override void DoEmit(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen)
{
if (!XamlIlAvaloniaPropertyHelper.Emit(context, codeGen, Property))
throw new XamlIlLoadException(
throw new XamlLoadException(
$"{Property.Name} of {(Property.Setter ?? Property.Getter).DeclaringType.GetFqn()} doesn't seem to be an AvaloniaProperty",
this);
context.Emit(Value, codeGen, context.Configuration.WellKnownTypes.Object);
@ -302,7 +306,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
class XamlIlOrSelectorNode : XamlIlSelectorNode
{
List<XamlIlSelectorNode> _selectors = new List<XamlIlSelectorNode>();
public XamlIlOrSelectorNode(IXamlIlLineInfo info, IXamlIlType selectorType) : base(null, info, selectorType)
public XamlIlOrSelectorNode(IXamlLineInfo info, IXamlType selectorType) : base(null, info, selectorType)
{
}
@ -311,11 +315,11 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
_selectors.Add(node);
}
public override IXamlIlType TargetType
public override IXamlType TargetType
{
get
{
IXamlIlType result = null;
IXamlType result = null;
foreach (var selector in _selectors)
{
@ -340,10 +344,10 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
}
}
protected override void DoEmit(XamlIlEmitContext context, IXamlIlEmitter codeGen)
protected override void DoEmit(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen)
{
if (_selectors.Count == 0)
throw new XamlIlLoadException("Invalid selector count", this);
throw new XamlLoadException("Invalid selector count", this);
if (_selectors.Count == 1)
{
_selectors[0].Emit(context, codeGen);

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

@ -1,64 +1,68 @@
using System;
using System.Collections.Generic;
using System.Linq;
using XamlIl;
using XamlIl.Ast;
using XamlIl.Transform;
using XamlIl.Transform.Transformers;
using XamlIl.TypeSystem;
using XamlX;
using XamlX.Ast;
using XamlX.Emit;
using XamlX.IL;
using XamlX.Transform;
using XamlX.Transform.Transformers;
using XamlX.TypeSystem;
namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{
class AvaloniaXamlIlSetterTransformer : IXamlIlAstTransformer
using XamlParseException = XamlX.XamlParseException;
using XamlLoadException = XamlX.XamlLoadException;
class AvaloniaXamlIlSetterTransformer : IXamlAstTransformer
{
public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node)
public IXamlAstNode Transform(AstTransformationContext context, IXamlAstNode node)
{
if (!(node is XamlIlAstObjectNode on
if (!(node is XamlAstObjectNode on
&& on.Type.GetClrType().FullName == "Avalonia.Styling.Setter"))
return node;
var parent = context.ParentNodes().OfType<XamlIlAstObjectNode>()
var parent = context.ParentNodes().OfType<XamlAstObjectNode>()
.FirstOrDefault(p => p.Type.GetClrType().FullName == "Avalonia.Styling.Style");
if (parent == null)
throw new XamlIlParseException(
throw new XamlParseException(
"Avalonia.Styling.Setter is only valid inside Avalonia.Styling.Style", node);
var selectorProperty = parent.Children.OfType<XamlIlAstXamlPropertyValueNode>()
var selectorProperty = parent.Children.OfType<XamlAstXamlPropertyValueNode>()
.FirstOrDefault(p => p.Property.GetClrProperty().Name == "Selector");
if (selectorProperty == null)
throw new XamlIlParseException(
throw new XamlParseException(
"Can not find parent Style Selector", node);
var selector = selectorProperty.Values.FirstOrDefault() as XamlIlSelectorNode;
if (selector?.TargetType == null)
throw new XamlIlParseException(
throw new XamlParseException(
"Can not resolve parent Style Selector type", node);
var property = @on.Children.OfType<XamlIlAstXamlPropertyValueNode>()
var property = @on.Children.OfType<XamlAstXamlPropertyValueNode>()
.FirstOrDefault(x => x.Property.GetClrProperty().Name == "Property");
if (property == null)
throw new XamlIlParseException("Setter without a property is not valid", node);
throw new XamlParseException("Setter without a property is not valid", node);
var propertyName = property.Values.OfType<XamlIlAstTextNode>().FirstOrDefault()?.Text;
var propertyName = property.Values.OfType<XamlAstTextNode>().FirstOrDefault()?.Text;
if (propertyName == null)
throw new XamlIlParseException("Setter.Property must be a string", node);
throw new XamlParseException("Setter.Property must be a string", node);
var avaloniaPropertyNode = XamlIlAvaloniaPropertyHelper.CreateNode(context, propertyName,
new XamlIlAstClrTypeReference(selector, selector.TargetType, false), property.Values[0]);
property.Values = new List<IXamlIlAstValueNode>
new XamlAstClrTypeReference(selector, selector.TargetType, false), property.Values[0]);
property.Values = new List<IXamlAstValueNode>
{
avaloniaPropertyNode
};
var valueProperty = on.Children
.OfType<XamlIlAstXamlPropertyValueNode>().FirstOrDefault(p => p.Property.GetClrProperty().Name == "Value");
if (valueProperty?.Values?.Count == 1 && valueProperty.Values[0] is XamlIlAstTextNode)
.OfType<XamlAstXamlPropertyValueNode>().FirstOrDefault(p => p.Property.GetClrProperty().Name == "Value");
if (valueProperty?.Values?.Count == 1 && valueProperty.Values[0] is XamlAstTextNode)
{
var propType = avaloniaPropertyNode.AvaloniaPropertyType;
if (!XamlIlTransformHelpers.TryGetCorrectlyTypedValue(context, valueProperty.Values[0],
if (!XamlTransformHelpers.TryGetCorrectlyTypedValue(context, valueProperty.Values[0],
propType, out var converted))
throw new XamlIlParseException(
throw new XamlParseException(
$"Unable to convert property value to {propType.GetFqn()}",
valueProperty.Values[0]);
@ -69,9 +73,9 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
return node;
}
class SetterValueProperty : XamlIlAstClrProperty
class SetterValueProperty : XamlAstClrProperty
{
public SetterValueProperty(IXamlIlLineInfo line, IXamlIlType setterType, IXamlIlType targetType,
public SetterValueProperty(IXamlLineInfo line, IXamlType setterType, IXamlType targetType,
AvaloniaXamlIlWellKnownTypes types)
: base(line, "Value", setterType, null)
{
@ -82,21 +86,21 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
Setters.Add(new XamlIlDirectCallPropertySetter(method, targetType));
}
class XamlIlDirectCallPropertySetter : IXamlIlPropertySetter
class XamlIlDirectCallPropertySetter : IXamlPropertySetter, IXamlEmitablePropertySetter<IXamlILEmitter>
{
private readonly IXamlIlMethod _method;
private readonly IXamlIlType _type;
public IXamlIlType TargetType { get; }
private readonly IXamlMethod _method;
private readonly IXamlType _type;
public IXamlType TargetType { get; }
public PropertySetterBinderParameters BinderParameters { get; } = new PropertySetterBinderParameters();
public IReadOnlyList<IXamlIlType> Parameters { get; }
public void Emit(IXamlIlEmitter codegen)
public IReadOnlyList<IXamlType> Parameters { get; }
public void Emit(IXamlILEmitter codegen)
{
if (_type.IsValueType)
codegen.Box(_type);
codegen.EmitCall(_method, true);
}
public XamlIlDirectCallPropertySetter(IXamlIlMethod method, IXamlIlType type)
public XamlIlDirectCallPropertySetter(IXamlMethod method, IXamlType type)
{
_method = method;
_type = type;

78
src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlTransformInstanceAttachedProperties.cs

@ -1,20 +1,22 @@
using System.Collections.Generic;
using System.Linq;
using XamlIl;
using XamlIl.Ast;
using XamlIl.Transform;
using XamlIl.TypeSystem;
using XamlX;
using XamlX.Ast;
using XamlX.Emit;
using XamlX.IL;
using XamlX.Transform;
using XamlX.TypeSystem;
namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{
class AvaloniaXamlIlTransformInstanceAttachedProperties : IXamlIlAstTransformer
class AvaloniaXamlIlTransformInstanceAttachedProperties : IXamlAstTransformer
{
public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node)
public IXamlAstNode Transform(AstTransformationContext context, IXamlAstNode node)
{
if (node is XamlIlAstNamePropertyReference prop
&& prop.TargetType is XamlIlAstClrTypeReference targetRef
&& prop.DeclaringType is XamlIlAstClrTypeReference declaringRef)
if (node is XamlAstNamePropertyReference prop
&& prop.TargetType is XamlAstClrTypeReference targetRef
&& prop.DeclaringType is XamlAstClrTypeReference declaringRef)
{
// Target and declared type aren't assignable but both inherit from AvaloniaObject
var avaloniaObject = context.Configuration.TypeSystem.FindType("Avalonia.AvaloniaObject");
@ -70,21 +72,21 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
return node;
}
class AvaloniaAttachedInstanceProperty : XamlIlAstClrProperty, IXamlIlAvaloniaProperty
class AvaloniaAttachedInstanceProperty : XamlAstClrProperty, IXamlIlAvaloniaProperty
{
private readonly XamlIlTransformerConfiguration _config;
private readonly IXamlIlType _declaringType;
private readonly IXamlIlType _avaloniaPropertyType;
private readonly IXamlIlType _avaloniaObject;
private readonly IXamlIlField _field;
public AvaloniaAttachedInstanceProperty(XamlIlAstNamePropertyReference prop,
XamlIlTransformerConfiguration config,
IXamlIlType declaringType,
IXamlIlType type,
IXamlIlType avaloniaPropertyType,
IXamlIlType avaloniaObject,
IXamlIlField field) : base(prop, prop.Name,
private readonly TransformerConfiguration _config;
private readonly IXamlType _declaringType;
private readonly IXamlType _avaloniaPropertyType;
private readonly IXamlType _avaloniaObject;
private readonly IXamlField _field;
public AvaloniaAttachedInstanceProperty(XamlAstNamePropertyReference prop,
TransformerConfiguration config,
IXamlType declaringType,
IXamlType type,
IXamlType avaloniaPropertyType,
IXamlType avaloniaObject,
IXamlField field) : base(prop, prop.Name,
declaringType, null)
@ -104,11 +106,11 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
Getter = new GetterMethod(this);
}
public IXamlIlType PropertyType { get; }
public IXamlType PropertyType { get; }
public IXamlIlField AvaloniaProperty => _field;
public IXamlField AvaloniaProperty => _field;
class SetterMethod : IXamlIlPropertySetter
class SetterMethod : IXamlPropertySetter, IXamlEmitablePropertySetter<IXamlILEmitter>
{
private readonly AvaloniaAttachedInstanceProperty _parent;
@ -118,10 +120,10 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
Parameters = new[] {_parent._avaloniaObject, _parent.PropertyType};
}
public IXamlIlType TargetType => _parent.DeclaringType;
public IXamlType TargetType => _parent.DeclaringType;
public PropertySetterBinderParameters BinderParameters { get; } = new PropertySetterBinderParameters();
public IReadOnlyList<IXamlIlType> Parameters { get; }
public void Emit(IXamlIlEmitter emitter)
public IReadOnlyList<IXamlType> Parameters { get; }
public void Emit(IXamlILEmitter emitter)
{
var so = _parent._config.WellKnownTypes.Object;
var method = _parent._avaloniaObject
@ -133,7 +135,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
&& m.Parameters[2].IsEnum
);
if (method == null)
throw new XamlIlTypeSystemException(
throw new XamlTypeSystemException(
"Unable to find SetValue(AvaloniaProperty, object, BindingPriority) on AvaloniaObject");
using (var loc = emitter.LocalsPool.GetLocal(_parent.PropertyType))
emitter
@ -150,7 +152,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
}
}
class GetterMethod : IXamlIlCustomEmitMethod
class GetterMethod : IXamlCustomEmitMethod<IXamlILEmitter>
{
public GetterMethod(AvaloniaAttachedInstanceProperty parent)
{
@ -163,16 +165,16 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
public bool IsPublic => true;
public bool IsStatic => true;
public string Name { get; protected set; }
public IXamlIlType DeclaringType { get; }
public IXamlIlMethod MakeGenericMethod(IReadOnlyList<IXamlIlType> typeArguments)
public IXamlType DeclaringType { get; }
public IXamlMethod MakeGenericMethod(IReadOnlyList<IXamlType> typeArguments)
=> throw new System.NotSupportedException();
public bool Equals(IXamlIlMethod other) =>
public bool Equals(IXamlMethod other) =>
other is GetterMethod m && m.Name == Name && m.DeclaringType.Equals(DeclaringType);
public IXamlIlType ReturnType => Parent.PropertyType;
public IReadOnlyList<IXamlIlType> Parameters { get; }
public void EmitCall(IXamlIlEmitter emitter)
public IXamlType ReturnType => Parent.PropertyType;
public IReadOnlyList<IXamlType> Parameters { get; }
public void EmitCall(IXamlILEmitter emitter)
{
var method = Parent._avaloniaObject
.FindMethod(m => m.IsPublic && !m.IsStatic && m.Name == "GetValue"
@ -180,7 +182,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
m.Parameters.Count == 1
&& m.Parameters[0].Equals(Parent._avaloniaPropertyType));
if (method == null)
throw new XamlIlTypeSystemException(
throw new XamlTypeSystemException(
"Unable to find T GetValue<T>(AvaloniaProperty<T>) on AvaloniaObject");
emitter
.Ldsfld(Parent._field)

12
src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlTransitionsTypeMetadataTransformer.cs

@ -1,17 +1,17 @@
using XamlIl.Ast;
using XamlIl.Transform;
using XamlX.Ast;
using XamlX.Transform;
namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{
class AvaloniaXamlIlTransitionsTypeMetadataTransformer : IXamlIlAstTransformer
class AvaloniaXamlIlTransitionsTypeMetadataTransformer : IXamlAstTransformer
{
public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node)
public IXamlAstNode Transform(AstTransformationContext context, IXamlAstNode node)
{
if (node is XamlIlAstObjectNode on)
if (node is XamlAstObjectNode on)
{
foreach (var ch in on.Children)
{
if (ch is XamlIlAstXamlPropertyValueNode pn
if (ch is XamlAstXamlPropertyValueNode pn
&& pn.Property.GetClrProperty().Getter?.ReturnType.Equals(context.GetAvaloniaTypes().Transitions) == true)
{
for (var c = 0; c < pn.Values.Count; c++)

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

@ -1,52 +1,54 @@
using XamlIl.Transform;
using XamlIl.TypeSystem;
using XamlX.Emit;
using XamlX.IL;
using XamlX.Transform;
using XamlX.TypeSystem;
namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{
class AvaloniaXamlIlWellKnownTypes
{
public IXamlIlType AvaloniaObject { get; }
public IXamlIlType IAvaloniaObject { get; }
public IXamlIlType BindingPriority { get; }
public IXamlIlType AvaloniaObjectExtensions { get; }
public IXamlIlType AvaloniaProperty { get; }
public IXamlIlType AvaloniaPropertyT { get; }
public IXamlIlType IBinding { get; }
public IXamlIlMethod AvaloniaObjectBindMethod { get; }
public IXamlIlMethod AvaloniaObjectSetValueMethod { get; }
public IXamlIlType IDisposable { get; }
public XamlIlTypeWellKnownTypes XamlIlTypes { get; }
public XamlIlLanguageTypeMappings XamlIlMappings { get; }
public IXamlIlType Transitions { get; }
public IXamlIlType AssignBindingAttribute { get; }
public IXamlIlType UnsetValueType { get; }
public IXamlIlType StyledElement { get; }
public IXamlIlType NameScope { get; }
public IXamlIlMethod NameScopeSetNameScope { get; }
public IXamlIlType INameScope { get; }
public IXamlIlMethod INameScopeRegister { get; }
public IXamlIlMethod INameScopeComplete { get; }
public IXamlType AvaloniaObject { get; }
public IXamlType IAvaloniaObject { get; }
public IXamlType BindingPriority { get; }
public IXamlType AvaloniaObjectExtensions { get; }
public IXamlType AvaloniaProperty { get; }
public IXamlType AvaloniaPropertyT { get; }
public IXamlType IBinding { get; }
public IXamlMethod AvaloniaObjectBindMethod { get; }
public IXamlMethod AvaloniaObjectSetValueMethod { get; }
public IXamlType IDisposable { get; }
public XamlTypeWellKnownTypes XamlIlTypes { get; }
public XamlLanguageTypeMappings XamlIlMappings { get; }
public IXamlType Transitions { get; }
public IXamlType AssignBindingAttribute { get; }
public IXamlType UnsetValueType { get; }
public IXamlType StyledElement { get; }
public IXamlType NameScope { get; }
public IXamlMethod NameScopeSetNameScope { get; }
public IXamlType INameScope { get; }
public IXamlMethod INameScopeRegister { get; }
public IXamlMethod INameScopeComplete { get; }
public AvaloniaXamlIlWellKnownTypes(XamlIlAstTransformationContext ctx)
public AvaloniaXamlIlWellKnownTypes(TransformerConfiguration config)
{
XamlIlTypes = ctx.Configuration.WellKnownTypes;
XamlIlMappings = ctx.Configuration.TypeMappings;
AvaloniaObject = ctx.Configuration.TypeSystem.GetType("Avalonia.AvaloniaObject");
IAvaloniaObject = ctx.Configuration.TypeSystem.GetType("Avalonia.IAvaloniaObject");
AvaloniaObjectExtensions = ctx.Configuration.TypeSystem.GetType("Avalonia.AvaloniaObjectExtensions");
AvaloniaProperty = ctx.Configuration.TypeSystem.GetType("Avalonia.AvaloniaProperty");
AvaloniaPropertyT = ctx.Configuration.TypeSystem.GetType("Avalonia.AvaloniaProperty`1");
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");
AssignBindingAttribute = ctx.Configuration.TypeSystem.GetType("Avalonia.Data.AssignBindingAttribute");
XamlIlTypes = config.WellKnownTypes;
XamlIlMappings = config.TypeMappings;
AvaloniaObject = config.TypeSystem.GetType("Avalonia.AvaloniaObject");
IAvaloniaObject = config.TypeSystem.GetType("Avalonia.IAvaloniaObject");
AvaloniaObjectExtensions = config.TypeSystem.GetType("Avalonia.AvaloniaObjectExtensions");
AvaloniaProperty = config.TypeSystem.GetType("Avalonia.AvaloniaProperty");
AvaloniaPropertyT = config.TypeSystem.GetType("Avalonia.AvaloniaProperty`1");
BindingPriority = config.TypeSystem.GetType("Avalonia.Data.BindingPriority");
IBinding = config.TypeSystem.GetType("Avalonia.Data.IBinding");
IDisposable = config.TypeSystem.GetType("System.IDisposable");
Transitions = config.TypeSystem.GetType("Avalonia.Animation.Transitions");
AssignBindingAttribute = config.TypeSystem.GetType("Avalonia.Data.AssignBindingAttribute");
AvaloniaObjectBindMethod = AvaloniaObjectExtensions.FindMethod("Bind", IDisposable, false, IAvaloniaObject,
AvaloniaProperty,
IBinding, ctx.Configuration.WellKnownTypes.Object);
UnsetValueType = ctx.Configuration.TypeSystem.GetType("Avalonia.UnsetValueType");
StyledElement = ctx.Configuration.TypeSystem.GetType("Avalonia.StyledElement");
INameScope = ctx.Configuration.TypeSystem.GetType("Avalonia.Controls.INameScope");
IBinding, config.WellKnownTypes.Object);
UnsetValueType = config.TypeSystem.GetType("Avalonia.UnsetValueType");
StyledElement = config.TypeSystem.GetType("Avalonia.StyledElement");
INameScope = config.TypeSystem.GetType("Avalonia.Controls.INameScope");
INameScopeRegister = INameScope.GetMethod(
new FindMethodMethodSignature("Register", XamlIlTypes.Void,
XamlIlTypes.String, XamlIlTypes.Object)
@ -58,7 +60,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{
IsStatic = false, DeclaringOnly = true, IsExactMatch = true
});
NameScope = ctx.Configuration.TypeSystem.GetType("Avalonia.Controls.NameScope");
NameScope = config.TypeSystem.GetType("Avalonia.Controls.NameScope");
NameScopeSetNameScope = NameScope.GetMethod(new FindMethodMethodSignature("SetNameScope",
XamlIlTypes.Void, StyledElement, INameScope) {IsStatic = true});
@ -70,11 +72,19 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
static class AvaloniaXamlIlWellKnownTypesExtensions
{
public static AvaloniaXamlIlWellKnownTypes GetAvaloniaTypes(this XamlIlAstTransformationContext ctx)
public static AvaloniaXamlIlWellKnownTypes GetAvaloniaTypes(this AstTransformationContext ctx)
{
if (ctx.TryGetItem<AvaloniaXamlIlWellKnownTypes>(out var rv))
return rv;
ctx.SetItem(rv = new AvaloniaXamlIlWellKnownTypes(ctx));
ctx.SetItem(rv = new AvaloniaXamlIlWellKnownTypes(ctx.Configuration));
return rv;
}
public static AvaloniaXamlIlWellKnownTypes GetAvaloniaTypes(this XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> ctx)
{
if (ctx.TryGetItem<AvaloniaXamlIlWellKnownTypes>(out var rv))
return rv;
ctx.SetItem(rv = new AvaloniaXamlIlWellKnownTypes(ctx.Configuration));
return rv;
}
}

14
src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/IgnoredDirectivesTransformer.cs

@ -1,17 +1,17 @@
using System.Linq;
using XamlIl;
using XamlIl.Ast;
using XamlIl.Transform;
using XamlX;
using XamlX.Ast;
using XamlX.Transform;
namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{
class IgnoredDirectivesTransformer : IXamlIlAstTransformer
class IgnoredDirectivesTransformer : IXamlAstTransformer
{
public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node)
public IXamlAstNode Transform(AstTransformationContext context, IXamlAstNode node)
{
if (node is XamlIlAstObjectNode no)
if (node is XamlAstObjectNode no)
{
foreach (var d in no.Children.OfType<XamlIlAstXmlDirective>().ToList())
foreach (var d in no.Children.OfType<XamlAstXmlDirective>().ToList())
{
if (d.Namespace == XamlNamespaces.Xaml2006)
{

19
src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/XNameTransformer.cs

@ -1,30 +1,29 @@
using XamlIl;
using XamlIl.Ast;
using XamlIl.Transform;
using XamlX;
using XamlX.Ast;
using XamlX.Transform;
namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{
class XNameTransformer : IXamlIlAstTransformer
class XNameTransformer : IXamlAstTransformer
{
/// <summary>
/// Converts x:Name directives to regular Name assignments
/// </summary>
/// <returns></returns>
public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node)
public IXamlAstNode Transform(AstTransformationContext context, IXamlAstNode node)
{
if (node is XamlIlAstObjectNode on)
if (node is XamlAstObjectNode on)
{
for (var c =0; c< on.Children.Count;c++)
{
var ch = on.Children[c];
if (ch is XamlIlAstXmlDirective d
if (ch is XamlAstXmlDirective d
&& d.Namespace == XamlNamespaces.Xaml2006
&& d.Name == "Name")
on.Children[c] = new XamlIlAstXamlPropertyValueNode(d,
new XamlIlAstNamePropertyReference(d, on.Type, "Name", on.Type),
on.Children[c] = new XamlAstXamlPropertyValueNode(d,
new XamlAstNamePropertyReference(d, on.Type, "Name", on.Type),
d.Values);
}
}

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

@ -5,17 +5,22 @@ using System.Xml;
using Avalonia.Markup.Xaml.Parsers;
using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers;
using Avalonia.Utilities;
using XamlIl;
using XamlIl.Ast;
using XamlIl.Transform;
using XamlIl.Transform.Transformers;
using XamlIl.TypeSystem;
using XamlX;
using XamlX.Ast;
using XamlX.Transform;
using XamlX.Transform.Transformers;
using XamlX.TypeSystem;
using XamlX.Emit;
using XamlX.IL;
using XamlIlEmitContext = XamlX.Emit.XamlEmitContext<XamlX.IL.IXamlILEmitter, XamlX.IL.XamlILNodeEmitResult>;
using IXamlIlAstEmitableNode = XamlX.Emit.IXamlAstEmitableNode<XamlX.IL.IXamlILEmitter, XamlX.IL.XamlILNodeEmitResult>;
namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
{
class XamlIlAvaloniaPropertyHelper
{
public static bool Emit(XamlIlEmitContext context, IXamlIlEmitter emitter, XamlIlAstClrProperty property)
public static bool Emit(XamlIlEmitContext context, IXamlILEmitter emitter, XamlAstClrProperty property)
{
if (property is IXamlIlAvaloniaProperty ap)
{
@ -32,7 +37,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
return true;
}
public static bool Emit(XamlIlEmitContext context, IXamlIlEmitter emitter, IXamlIlProperty property)
public static bool Emit(XamlIlEmitContext context, IXamlILEmitter emitter, IXamlProperty property)
{
var type = (property.Getter ?? property.Setter).DeclaringType;
var name = property.Name + "Property";
@ -44,16 +49,16 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
return true;
}
public static IXamlIlAvaloniaPropertyNode CreateNode(XamlIlAstTransformationContext context,
string propertyName, IXamlIlAstTypeReference selectorTypeReference, IXamlIlLineInfo lineInfo)
public static IXamlIlAvaloniaPropertyNode CreateNode(AstTransformationContext context,
string propertyName, IXamlAstTypeReference selectorTypeReference, IXamlLineInfo lineInfo)
{
XamlIlAstNamePropertyReference forgedReference;
XamlAstNamePropertyReference forgedReference;
var parser = new PropertyParser();
var parsedPropertyName = parser.Parse(new CharacterReader(propertyName.AsSpan()));
if(parsedPropertyName.owner == null)
forgedReference = new XamlIlAstNamePropertyReference(lineInfo, selectorTypeReference,
forgedReference = new XamlAstNamePropertyReference(lineInfo, selectorTypeReference,
propertyName, selectorTypeReference);
else
{
@ -62,19 +67,19 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
xmlOwner += ":";
xmlOwner += parsedPropertyName.owner;
var tref = XamlIlTypeReferenceResolver.ResolveType(context, xmlOwner, false, lineInfo, true);
var tref = TypeReferenceResolver.ResolveType(context, xmlOwner, false, lineInfo, true);
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(
throw new XamlX.XamlParseException(
$"Unable to find {propertyFieldName} field on type {tref.Type.GetFullName()}", lineInfo);
return new XamlIlAvaloniaPropertyFieldNode(context.GetAvaloniaTypes(), lineInfo, found);
}
var clrProperty =
((XamlIlAstClrProperty)new XamlIlPropertyReferenceResolver().Transform(context,
((XamlAstClrProperty)new PropertyReferenceResolver().Transform(context,
forgedReference));
return new XamlIlAvaloniaPropertyNode(lineInfo,
context.Configuration.TypeSystem.GetType("Avalonia.AvaloniaProperty"),
@ -82,40 +87,40 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
}
}
interface IXamlIlAvaloniaPropertyNode : IXamlIlAstValueNode
interface IXamlIlAvaloniaPropertyNode : IXamlAstValueNode
{
IXamlIlType AvaloniaPropertyType { get; }
IXamlType AvaloniaPropertyType { get; }
}
class XamlIlAvaloniaPropertyNode : XamlIlAstNode, IXamlIlAstValueNode, IXamlIlAstEmitableNode, IXamlIlAvaloniaPropertyNode
class XamlIlAvaloniaPropertyNode : XamlAstNode, IXamlAstValueNode, IXamlIlAstEmitableNode, IXamlIlAvaloniaPropertyNode
{
public XamlIlAvaloniaPropertyNode(IXamlIlLineInfo lineInfo, IXamlIlType type, XamlIlAstClrProperty property) : base(lineInfo)
public XamlIlAvaloniaPropertyNode(IXamlLineInfo lineInfo, IXamlType type, XamlAstClrProperty property) : base(lineInfo)
{
Type = new XamlIlAstClrTypeReference(this, type, false);
Type = new XamlAstClrTypeReference(this, type, false);
Property = property;
AvaloniaPropertyType = Property.Getter?.ReturnType
?? Property.Setters.First().Parameters[0];
}
public XamlIlAstClrProperty Property { get; }
public XamlAstClrProperty Property { get; }
public IXamlIlAstTypeReference Type { get; }
public XamlIlNodeEmitResult Emit(XamlIlEmitContext context, IXamlIlEmitter codeGen)
public IXamlAstTypeReference 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());
throw new XamlX.XamlLoadException(Property.Name + " is not an AvaloniaProperty", this);
return XamlILNodeEmitResult.Type(0, Type.GetClrType());
}
public IXamlIlType AvaloniaPropertyType { get; }
public IXamlType AvaloniaPropertyType { get; }
}
class XamlIlAvaloniaPropertyFieldNode : XamlIlAstNode, IXamlIlAstValueNode, IXamlIlAstEmitableNode, IXamlIlAvaloniaPropertyNode
class XamlIlAvaloniaPropertyFieldNode : XamlAstNode, IXamlAstValueNode, IXamlIlAstEmitableNode, IXamlIlAvaloniaPropertyNode
{
private readonly IXamlIlField _field;
private readonly IXamlField _field;
public XamlIlAvaloniaPropertyFieldNode(AvaloniaXamlIlWellKnownTypes types,
IXamlIlLineInfo lineInfo, IXamlIlField field) : base(lineInfo)
IXamlLineInfo lineInfo, IXamlField field) : base(lineInfo)
{
_field = field;
var avaloniaPropertyType = field.FieldType;
@ -130,7 +135,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
avaloniaPropertyType = avaloniaPropertyType.BaseType;
}
throw new XamlIlParseException(
throw new XamlX.XamlParseException(
$"{field.Name}'s type {field.FieldType} doesn't inherit from AvaloniaProperty<T>, make sure to use typed properties",
lineInfo);
@ -138,25 +143,25 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
public IXamlIlAstTypeReference Type => new XamlIlAstClrTypeReference(this, _field.FieldType, false);
public XamlIlNodeEmitResult Emit(XamlIlEmitContext context, IXamlIlEmitter codeGen)
public IXamlAstTypeReference Type => new XamlAstClrTypeReference(this, _field.FieldType, false);
public XamlILNodeEmitResult Emit(XamlIlEmitContext context, IXamlILEmitter codeGen)
{
codeGen.Ldsfld(_field);
return XamlIlNodeEmitResult.Type(0, _field.FieldType);
return XamlILNodeEmitResult.Type(0, _field.FieldType);
}
public IXamlIlType AvaloniaPropertyType { get; }
public IXamlType AvaloniaPropertyType { get; }
}
interface IXamlIlAvaloniaProperty
{
IXamlIlField AvaloniaProperty { get; }
IXamlField AvaloniaProperty { get; }
}
class XamlIlAvaloniaProperty : XamlIlAstClrProperty, IXamlIlAvaloniaProperty
class XamlIlAvaloniaProperty : XamlAstClrProperty, IXamlIlAvaloniaProperty
{
public IXamlIlField AvaloniaProperty { get; }
public XamlIlAvaloniaProperty(XamlIlAstClrProperty original, IXamlIlField field,
public IXamlField AvaloniaProperty { get; }
public XamlIlAvaloniaProperty(XamlAstClrProperty original, IXamlField field,
AvaloniaXamlIlWellKnownTypes types)
:base(original, original.Name, original.DeclaringType, original.Getter, original.Setters)
{
@ -168,41 +173,41 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
Setters.Insert(0, new UnsetValueSetter(types, original.DeclaringType, field));
}
abstract class AvaloniaPropertyCustomSetter : IXamlIlPropertySetter
abstract class AvaloniaPropertyCustomSetter : IXamlPropertySetter, IXamlEmitablePropertySetter<IXamlILEmitter>
{
protected AvaloniaXamlIlWellKnownTypes Types;
protected IXamlIlField AvaloniaProperty;
protected IXamlField AvaloniaProperty;
public AvaloniaPropertyCustomSetter(AvaloniaXamlIlWellKnownTypes types,
IXamlIlType declaringType,
IXamlIlField avaloniaProperty)
IXamlType declaringType,
IXamlField avaloniaProperty)
{
Types = types;
AvaloniaProperty = avaloniaProperty;
TargetType = declaringType;
}
public IXamlIlType TargetType { get; }
public IXamlType TargetType { get; }
public PropertySetterBinderParameters BinderParameters { get; } = new PropertySetterBinderParameters
{
AllowXNull = false
};
public IReadOnlyList<IXamlIlType> Parameters { get; set; }
public abstract void Emit(IXamlIlEmitter codegen);
public IReadOnlyList<IXamlType> Parameters { get; set; }
public abstract void Emit(IXamlILEmitter codegen);
}
class BindingSetter : AvaloniaPropertyCustomSetter
{
public BindingSetter(AvaloniaXamlIlWellKnownTypes types,
IXamlIlType declaringType,
IXamlIlField avaloniaProperty) : base(types, declaringType, avaloniaProperty)
IXamlType declaringType,
IXamlField avaloniaProperty) : base(types, declaringType, avaloniaProperty)
{
Parameters = new[] {types.IBinding};
}
public override void Emit(IXamlIlEmitter emitter)
public override void Emit(IXamlILEmitter emitter)
{
using (var bloc = emitter.LocalsPool.GetLocal(Types.IBinding))
emitter
@ -217,13 +222,13 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
class UnsetValueSetter : AvaloniaPropertyCustomSetter
{
public UnsetValueSetter(AvaloniaXamlIlWellKnownTypes types, IXamlIlType declaringType, IXamlIlField avaloniaProperty)
public UnsetValueSetter(AvaloniaXamlIlWellKnownTypes types, IXamlType declaringType, IXamlField avaloniaProperty)
: base(types, declaringType, avaloniaProperty)
{
Parameters = new[] {types.UnsetValueType};
}
public override void Emit(IXamlIlEmitter codegen)
public override void Emit(IXamlILEmitter codegen)
{
var unsetValue = Types.AvaloniaProperty.Fields.First(f => f.Name == "UnsetValue");
codegen

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

@ -1 +1 @@
Subproject commit 068162245473ec39ee36da12150e928072b96403
Subproject commit 32702e32fabf2ddda28a740d8e17937678d57344
Loading…
Cancel
Save