AvaloniaXamlIlRootObjectScopeTransformer.cs 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. using System;
  2. using System.Linq;
  3. using XamlX;
  4. using XamlX.Ast;
  5. using XamlX.Transform;
  6. using XamlX.TypeSystem;
  7. using XamlX.IL;
  8. using XamlX.Emit;
  9. namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
  10. {
  11. class AvaloniaXamlIlRootObjectScope : IXamlAstTransformer
  12. {
  13. public IXamlAstNode Transform(AstTransformationContext context, IXamlAstNode node)
  14. {
  15. if (!context.ParentNodes().Any()
  16. && node is XamlValueWithManipulationNode mnode)
  17. {
  18. mnode.Manipulation = new XamlManipulationGroupNode(mnode,
  19. new[]
  20. {
  21. mnode.Manipulation,
  22. new HandleRootObjectScopeNode(mnode, context.GetAvaloniaTypes())
  23. });
  24. }
  25. return node;
  26. }
  27. class HandleRootObjectScopeNode : XamlAstNode, IXamlAstManipulationNode
  28. {
  29. private readonly AvaloniaXamlIlWellKnownTypes _types;
  30. public HandleRootObjectScopeNode(IXamlLineInfo lineInfo,
  31. AvaloniaXamlIlWellKnownTypes types) : base(lineInfo)
  32. {
  33. _types = types;
  34. }
  35. }
  36. internal class Emitter : IXamlILAstNodeEmitter
  37. {
  38. public XamlILNodeEmitResult Emit(IXamlAstNode node, XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen)
  39. {
  40. if (!(node is HandleRootObjectScopeNode))
  41. {
  42. return null;
  43. }
  44. var types = context.GetAvaloniaTypes();
  45. var next = codeGen.DefineLabel();
  46. var scopeField = context.RuntimeContext.ContextType.Fields.First(f =>
  47. f.Name == AvaloniaXamlIlLanguage.ContextNameScopeFieldName);
  48. using (var local = codeGen.LocalsPool.GetLocal(types.StyledElement))
  49. {
  50. codeGen
  51. .Isinst(types.StyledElement)
  52. .Dup()
  53. .Stloc(local.Local)
  54. .Brfalse(next)
  55. .Ldloc(local.Local)
  56. .Ldloc(context.ContextLocal)
  57. .Ldfld(scopeField)
  58. .EmitCall(types.NameScopeSetNameScope, true)
  59. .MarkLabel(next)
  60. .Ldloc(context.ContextLocal)
  61. .Ldfld(scopeField)
  62. .EmitCall(types.INameScopeComplete, true);
  63. }
  64. return XamlILNodeEmitResult.Void(1);
  65. }
  66. }
  67. }
  68. }