public ProxyXamlMember(IXamlType owner, MemberMeta meta)
 {
     _owner = owner;
     _meta = meta;
 }
Example #2
0
        public IXamlAstNode Transform(AstTransformationContext context, IXamlAstNode node)
        {
            if (node is XamlAstXamlPropertyValueNode valueNode)
            {
                var property    = valueNode.Property.GetClrProperty();
                var assignments = new List <XamlPropertyAssignmentNode>();
                foreach (var v in valueNode.Values)
                {
                    var keyNode   = FindAndRemoveKey(v);
                    var arguments = new List <IXamlAstValueNode>();

                    if (keyNode != null)
                    {
                        arguments.Add(keyNode);
                    }
                    arguments.Add(v);


                    // Pre-filter setters by non-last argument
                    var filteredSetters = property.Setters.Where(s => s.Parameters.Count == arguments.Count)
                                          .ToList();

                    if (arguments.Count > 1)
                    {
                        for (var c = 0; c < arguments.Count - 1; c++)
                        {
                            IXamlType convertedTo = null;
                            for (var s = 0; s < filteredSetters.Count;)
                            {
                                var setter = filteredSetters[s];
                                if (convertedTo == null)
                                {
                                    if (!XamlTransformHelpers.TryGetCorrectlyTypedValue(context, arguments[c],
                                                                                        setter.Parameters[c], out var converted))
                                    {
                                        filteredSetters.RemoveAt(c);
                                        continue;
                                    }
                                    else
                                    {
                                        convertedTo  = converted.Type.GetClrType();
                                        arguments[c] = converted;
                                    }
                                }
                                else
                                {
                                    if (!setter.Parameters[c].IsAssignableFrom(convertedTo))
                                    {
                                        throw new XamlLoadException(
                                                  $"Runtime setter selection is not supported for non-last setter arguments (e. g. x:Key) and can not downcast argument {c} of the setter from {convertedTo} to {setter.Parameters[c]}",
                                                  arguments[c]);
                                    }
                                }
                                s++;
                            }
                        }
                    }

                    XamlPropertyAssignmentNode CreateAssignment()
                    {
                        var matchedSetters = new List <IXamlPropertySetter>();

                        foreach (var setter in filteredSetters)
                        {
                            bool CanAssign(IXamlAstValueNode value, IXamlType type)
                            {
                                // Don't allow x:Null
                                if (!setter.BinderParameters.AllowXNull &&
                                    XamlPseudoType.Null.Equals(value.Type.GetClrType()))
                                {
                                    return(false);
                                }

                                // Direct cast
                                if (type.IsAssignableFrom(value.Type.GetClrType()))
                                {
                                    return(true);
                                }

                                // Upcast from System.Object
                                if (value.Type.GetClrType().Equals(context.Configuration.WellKnownTypes.Object))
                                {
                                    return(true);
                                }

                                return(false);
                            }

                            var valueArgIndex = arguments.Count - 1;
                            var valueArg      = arguments[valueArgIndex];
                            var setterType    = setter.Parameters[valueArgIndex];

                            if (CanAssign(valueArg, setterType))
                            {
                                matchedSetters.Add(setter);
                            }
                            // Converted value have more priority than custom setters, so we just create a setter without an alternative
                            else if (XamlTransformHelpers.TryConvertValue(context, valueArg, setterType, property,
                                                                          out var converted))
                            {
                                arguments[valueArgIndex] = converted;
                                return(new XamlPropertyAssignmentNode(valueNode,
                                                                      property, new[] { setter }, arguments));
                            }
                        }

                        if (matchedSetters.Count > 0)
                        {
                            return(new XamlPropertyAssignmentNode(v, property, matchedSetters, arguments));
                        }

                        throw new XamlLoadException(
                                  $"Unable to find suitable setter or adder for property {property.Name} of type {property.DeclaringType.GetFqn()} for argument {v.Type.GetClrType().GetFqn()}"
                                  + (keyNode != null ? $" and x:Key of type {keyNode.Type.GetClrType()}" : null)
                                  + ", available setter parameter lists are:\n" + string.Join("\n",
                                                                                              filteredSetters.Select(setter =>
                                                                                                                     string.Join(", ", setter.Parameters.Select(p => p.FullName))))
                                  , v);
                    }

                    assignments.Add(CreateAssignment());
                }

                if (assignments.Count == 1)
                {
                    return(assignments[0]);
                }

                if (assignments.Count > 1)
                {
                    // Skip the first one, since we only care about further setters, e. g. the following is perfectly valid:
                    // <Foo.Bar>
                    //   <SomeList/>
                    //   <ListItem/>
                    //   <ListItem/>
                    // </Foo.Bar>
                    // <SomeList/> would be foo.Bar = new SomeList() and <ListItem/> would be foo.Bar.Add(new ListItem());
                    foreach (var ass in assignments.Skip(1))
                    {
                        ass.PossibleSetters = ass.PossibleSetters.Where(s => s.BinderParameters.AllowMultiple).ToList();
                        if (ass.PossibleSetters.Count == 0)
                        {
                            throw new XamlLoadException(
                                      $"Unable to find a setter that allows multiple assignments to the property {ass.Property.Name} of type {ass.Property.DeclaringType.GetFqn()}",
                                      node);
                        }
                    }
                }

                return(new XamlManipulationGroupNode(valueNode, assignments));
            }

            return(node);
        }
Example #3
0
 protected abstract void EmitConvert(IXamlAstNode value, TBackendEmitter codeGen, IXamlType expectedType, IXamlType returnedType);
 public bool Equals(IXamlType other) =>
 other is RoslynType roslynType &&
Example #5
0
 public XamlIlTypeSelector(XamlIlSelectorNode previous, IXamlType type, bool concrete) : base(previous)
 {
     TargetType = type;
     Concrete   = concrete;
 }
 private bool IsControl(IXamlType type) => type.FullName != "System.Object" &&
 (type.FullName == "Robust.Client.UserInterface.Control" ||
  IsControl(type.BaseType));
Example #7
0
        protected override void EmitConvert(IXamlAstNode value, IXamlILEmitter codeGen, IXamlType expectedType, IXamlType returnedType)
        {
            XamlLocalsPool.PooledLocal local = null;
            // ReSharper disable once ExpressionIsAlwaysNull
            // Value is assigned inside the closure in certain conditions

            ILEmitHelpers.EmitConvert(this, value, returnedType, expectedType, ldaddr =>
            {
                if (ldaddr && returnedType.IsValueType)
                {
                    // We need to store the value to a temporary variable, since *address*
                    // is required (probably for  method call on the value type)
                    local = GetLocalOfType(returnedType);
                    codeGen
                    .Stloc(local.Local)
                    .Ldloca(local.Local);
                }
                // Otherwise do nothing, value is already at the top of the stack
                return(codeGen);
            });
            local?.Dispose();
        }
 public ViewModelXamlMember(string propertyName, ViewModelXamlType <T> targetType, IXamlType propertyType)
 {
     _propertyName = propertyName;
     _targetType   = targetType;
     _propertyType = propertyType;
 }
Example #9
0
 public bool Equals(IXamlType other) => other == this;
Example #10
0
 public XamlIlNestingSelector(XamlIlSelectorNode previous, IXamlType targetType)
     : base(previous)
 {
     TargetType = targetType;
 }
Example #11
0
 public void ChangeEmitSetterType(IXamlType setterType)
 {
     Parameters = new [] { setterType };
 }
Example #12
0
        public AvaloniaXamlIlWellKnownTypes(TransformerConfiguration cfg)
        {
            XamlIlTypes              = cfg.WellKnownTypes;
            AvaloniaObject           = cfg.TypeSystem.GetType("Avalonia.AvaloniaObject");
            IAvaloniaObject          = cfg.TypeSystem.GetType("Avalonia.IAvaloniaObject");
            AvaloniaObjectExtensions = cfg.TypeSystem.GetType("Avalonia.AvaloniaObjectExtensions");
            AvaloniaProperty         = cfg.TypeSystem.GetType("Avalonia.AvaloniaProperty");
            AvaloniaPropertyT        = cfg.TypeSystem.GetType("Avalonia.AvaloniaProperty`1");
            BindingPriority          = cfg.TypeSystem.GetType("Avalonia.Data.BindingPriority");
            IBinding                 = cfg.TypeSystem.GetType("Avalonia.Data.IBinding");
            IDisposable              = cfg.TypeSystem.GetType("System.IDisposable");
            Transitions              = cfg.TypeSystem.GetType("Avalonia.Animation.Transitions");
            AssignBindingAttribute   = cfg.TypeSystem.GetType("Avalonia.Data.AssignBindingAttribute");
            AvaloniaObjectBindMethod = AvaloniaObjectExtensions.FindMethod("Bind", IDisposable, false, IAvaloniaObject,
                                                                           AvaloniaProperty,
                                                                           IBinding, cfg.WellKnownTypes.Object);
            UnsetValueType     = cfg.TypeSystem.GetType("Avalonia.UnsetValueType");
            StyledElement      = cfg.TypeSystem.GetType("Avalonia.StyledElement");
            INameScope         = cfg.TypeSystem.GetType("Avalonia.Controls.INameScope");
            INameScopeRegister = INameScope.GetMethod(
                new FindMethodMethodSignature("Register", XamlIlTypes.Void,
                                              XamlIlTypes.String, XamlIlTypes.Object)
            {
                IsStatic      = false,
                DeclaringOnly = true,
                IsExactMatch  = true
            });
            INameScopeComplete = INameScope.GetMethod(
                new FindMethodMethodSignature("Complete", XamlIlTypes.Void)
            {
                IsStatic      = false,
                DeclaringOnly = true,
                IsExactMatch  = true
            });
            NameScope             = cfg.TypeSystem.GetType("Avalonia.Controls.NameScope");
            NameScopeSetNameScope = NameScope.GetMethod(new FindMethodMethodSignature("SetNameScope",
                                                                                      XamlIlTypes.Void, StyledElement, INameScope)
            {
                IsStatic = true
            });
            AvaloniaObjectSetValueMethod = AvaloniaObject.FindMethod("SetValue", XamlIlTypes.Void,
                                                                     false, AvaloniaProperty, XamlIlTypes.Object, BindingPriority);
            IPropertyInfo               = cfg.TypeSystem.GetType("Avalonia.Data.Core.IPropertyInfo");
            ClrPropertyInfo             = cfg.TypeSystem.GetType("Avalonia.Data.Core.ClrPropertyInfo");
            PropertyPath                = cfg.TypeSystem.GetType("Avalonia.Data.Core.PropertyPath");
            PropertyPathBuilder         = cfg.TypeSystem.GetType("Avalonia.Data.Core.PropertyPathBuilder");
            IPropertyAccessor           = cfg.TypeSystem.GetType("Avalonia.Data.Core.Plugins.IPropertyAccessor");
            PropertyInfoAccessorFactory = cfg.TypeSystem.GetType("Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings.PropertyInfoAccessorFactory");
            CompiledBindingPathBuilder  = cfg.TypeSystem.GetType("Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings.CompiledBindingPathBuilder");
            CompiledBindingPath         = cfg.TypeSystem.GetType("Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings.CompiledBindingPath");
            CompiledBindingExtension    = cfg.TypeSystem.GetType("Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindingExtension");
            ResolveByNameExtension      = cfg.TypeSystem.GetType("Avalonia.Markup.Xaml.MarkupExtensions.ResolveByNameExtension");
            DataTemplate                = cfg.TypeSystem.GetType("Avalonia.Markup.Xaml.Templates.DataTemplate");
            IDataTemplate               = cfg.TypeSystem.GetType("Avalonia.Controls.Templates.IDataTemplate");
            IItemsPresenterHost         = cfg.TypeSystem.GetType("Avalonia.Controls.Presenters.IItemsPresenterHost");
            ItemsRepeater               = cfg.TypeSystem.GetType("Avalonia.Controls.ItemsRepeater");
            ReflectionBindingExtension  = cfg.TypeSystem.GetType("Avalonia.Markup.Xaml.MarkupExtensions.ReflectionBindingExtension");
            RelativeSource              = cfg.TypeSystem.GetType("Avalonia.Data.RelativeSource");
            UInt       = cfg.TypeSystem.GetType("System.UInt32");
            Int        = cfg.TypeSystem.GetType("System.Int32");
            Long       = cfg.TypeSystem.GetType("System.Int64");
            Uri        = cfg.TypeSystem.GetType("System.Uri");
            FontFamily = cfg.TypeSystem.GetType("Avalonia.Media.FontFamily");
            FontFamilyConstructorUriName = FontFamily.GetConstructor(new List <IXamlType> {
                Uri, XamlIlTypes.String
            });

            (IXamlType, IXamlConstructor) GetNumericTypeInfo(string name, IXamlType componentType, int componentCount)
            {
                var type = cfg.TypeSystem.GetType(name);
                var ctor = type.GetConstructor(Enumerable.Range(0, componentCount).Select(_ => componentType).ToList());

                return(type, ctor);
            }

            (Thickness, ThicknessFullConstructor)       = GetNumericTypeInfo("Avalonia.Thickness", XamlIlTypes.Double, 4);
            (Point, PointFullConstructor)               = GetNumericTypeInfo("Avalonia.Point", XamlIlTypes.Double, 2);
            (Vector, VectorFullConstructor)             = GetNumericTypeInfo("Avalonia.Vector", XamlIlTypes.Double, 2);
            (Size, SizeFullConstructor)                 = GetNumericTypeInfo("Avalonia.Size", XamlIlTypes.Double, 2);
            (Matrix, MatrixFullConstructor)             = GetNumericTypeInfo("Avalonia.Matrix", XamlIlTypes.Double, 6);
            (CornerRadius, CornerRadiusFullConstructor) = GetNumericTypeInfo("Avalonia.CornerRadius", XamlIlTypes.Double, 4);

            GridLength = cfg.TypeSystem.GetType("Avalonia.Controls.GridLength");
            GridLengthConstructorValueType = GridLength.GetConstructor(new List <IXamlType> {
                XamlIlTypes.Double, cfg.TypeSystem.GetType("Avalonia.Controls.GridUnitType")
            });
            Color = cfg.TypeSystem.GetType("Avalonia.Media.Color");
            StandardCursorType    = cfg.TypeSystem.GetType("Avalonia.Input.StandardCursorType");
            Cursor                = cfg.TypeSystem.GetType("Avalonia.Input.Cursor");
            CursorTypeConstructor = Cursor.GetConstructor(new List <IXamlType> {
                StandardCursorType
            });
            ColumnDefinition  = cfg.TypeSystem.GetType("Avalonia.Controls.ColumnDefinition");
            ColumnDefinitions = cfg.TypeSystem.GetType("Avalonia.Controls.ColumnDefinitions");
            RowDefinition     = cfg.TypeSystem.GetType("Avalonia.Controls.RowDefinition");
            RowDefinitions    = cfg.TypeSystem.GetType("Avalonia.Controls.RowDefinitions");
        }
 public ProxyXamlMember(IXamlType owner, MemberMeta meta)
 {
     _owner = owner;
     _meta  = meta;
 }
 public AvaloniaXamlIlDataContextTypeMetadataNode(IXamlAstValueNode value, IXamlType targetType)
     : base(value, value)
 {
     DataContextType = targetType;
 }
Example #15
0
        public static bool TryConvert(AstTransformationContext context, IXamlAstValueNode node, string text, IXamlType type, AvaloniaXamlIlWellKnownTypes types, out IXamlAstValueNode result)
        {
            if (type.FullName == "System.TimeSpan")
            {
                var tsText = text.Trim();

                if (!TimeSpan.TryParse(tsText, CultureInfo.InvariantCulture, out var timeSpan))
                {
                    // // shorthand seconds format (ie. "0.25")
                    if (!tsText.Contains(":") && double.TryParse(tsText,
                                                                 NumberStyles.Float | NumberStyles.AllowThousands,
                                                                 CultureInfo.InvariantCulture, out var seconds))
                    {
                        timeSpan = TimeSpan.FromSeconds(seconds);
                    }
                    else
                    {
                        throw new XamlX.XamlLoadException($"Unable to parse {text} as a time span", node);
                    }
                }

                result = new XamlStaticOrTargetedReturnMethodCallNode(node,
                                                                      type.FindMethod("FromTicks", type, false, types.Long),
                                                                      new[] { new XamlConstantNode(node, types.Long, timeSpan.Ticks) });
                return(true);
            }

            if (type.Equals(types.FontFamily))
            {
                result = new AvaloniaXamlIlFontFamilyAstNode(types, text, node);
                return(true);
            }

            if (type.Equals(types.Thickness))
            {
                try
                {
                    var thickness = Thickness.Parse(text);

                    result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Thickness, types.ThicknessFullConstructor,
                                                                         new[] { thickness.Left, thickness.Top, thickness.Right, thickness.Bottom });

                    return(true);
                }
                catch
                {
                    throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a thickness", node);
                }
            }

            if (type.Equals(types.Point))
            {
                try
                {
                    var point = Point.Parse(text);

                    result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Point, types.PointFullConstructor,
                                                                         new[] { point.X, point.Y });

                    return(true);
                }
                catch
                {
                    throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a point", node);
                }
            }

            if (type.Equals(types.Vector))
            {
                try
                {
                    var vector = Vector.Parse(text);

                    result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Vector, types.VectorFullConstructor,
                                                                         new[] { vector.X, vector.Y });

                    return(true);
                }
                catch
                {
                    throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a vector", node);
                }
            }

            if (type.Equals(types.Size))
            {
                try
                {
                    var size = Size.Parse(text);

                    result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Size, types.SizeFullConstructor,
                                                                         new[] { size.Width, size.Height });

                    return(true);
                }
                catch
                {
                    throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a size", node);
                }
            }

            if (type.Equals(types.Matrix))
            {
                try
                {
                    var matrix = Matrix.Parse(text);

                    result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Matrix, types.MatrixFullConstructor,
                                                                         new[] { matrix.M11, matrix.M12, matrix.M21, matrix.M22, matrix.M31, matrix.M32 });

                    return(true);
                }
                catch
                {
                    throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a matrix", node);
                }
            }

            if (type.Equals(types.CornerRadius))
            {
                try
                {
                    var cornerRadius = CornerRadius.Parse(text);

                    result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.CornerRadius, types.CornerRadiusFullConstructor,
                                                                         new[] { cornerRadius.TopLeft, cornerRadius.TopRight, cornerRadius.BottomRight, cornerRadius.BottomLeft });

                    return(true);
                }
                catch
                {
                    throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a corner radius", node);
                }
            }

            if (type.Equals(types.Color))
            {
                if (!Color.TryParse(text, out Color color))
                {
                    throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a color", node);
                }

                result = new XamlStaticOrTargetedReturnMethodCallNode(node,
                                                                      type.GetMethod(
                                                                          new FindMethodMethodSignature("FromUInt32", type, types.UInt)
                {
                    IsStatic = true
                }),
                                                                      new[] { new XamlConstantNode(node, types.UInt, color.ToUint32()) });

                return(true);
            }

            if (type.Equals(types.GridLength))
            {
                try
                {
                    var gridLength = GridLength.Parse(text);

                    result = new AvaloniaXamlIlGridLengthAstNode(node, types, gridLength);

                    return(true);
                }
                catch
                {
                    throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a grid length", node);
                }
            }

            if (type.Equals(types.Cursor))
            {
                if (TypeSystemHelpers.TryGetEnumValueNode(types.StandardCursorType, text, node, out var enumConstantNode))
                {
                    var cursorTypeRef = new XamlAstClrTypeReference(node, types.Cursor, false);

                    result = new XamlAstNewClrObjectNode(node, cursorTypeRef, types.CursorTypeConstructor, new List <IXamlAstValueNode> {
                        enumConstantNode
                    });

                    return(true);
                }
            }

            if (type.Equals(types.ColumnDefinitions))
            {
                return(ConvertDefinitionList(node, text, types, types.ColumnDefinitions, types.ColumnDefinition, "column definitions", out result));
            }

            if (type.Equals(types.RowDefinitions))
            {
                return(ConvertDefinitionList(node, text, types, types.RowDefinitions, types.RowDefinition, "row definitions", out result));
            }

            if (type.Equals(types.Classes))
            {
                var classes    = text.Split(' ');
                var classNodes = classes.Select(c => new XamlAstTextNode(node, c, type: types.XamlIlTypes.String)).ToArray();

                result = new AvaloniaXamlIlAvaloniaListConstantAstNode(node, types, types.Classes, types.XamlIlTypes.String, classNodes);
                return(true);
            }

            if (types.IBrush.IsAssignableFrom(type))
            {
                if (Color.TryParse(text, out Color color))
                {
                    var brushTypeRef = new XamlAstClrTypeReference(node, types.ImmutableSolidColorBrush, false);

                    result = new XamlAstNewClrObjectNode(node, brushTypeRef,
                                                         types.ImmutableSolidColorBrushConstructorColor,
                                                         new List <IXamlAstValueNode> {
                        new XamlConstantNode(node, types.UInt, color.ToUint32())
                    });

                    return(true);
                }
            }

            result = null;
            return(false);
        }
Example #16
0
 public bool IsAssignableFrom(IXamlType type) => type == this;
 public AvaloniaXamlIlCompiler(TransformerConfiguration configuration,
                               XamlLanguageEmitMappings <IXamlILEmitter, XamlILNodeEmitResult> emitMappings,
                               IXamlType contextType) : this(configuration, emitMappings)
 {
     _contextType = contextType;
 }
Example #18
0
 public FindMethodMethodSignature(string name, IXamlType returnType, params IXamlType[] parameters)
 {
     Name       = name;
     ReturnType = returnType;
     Parameters = parameters;
 }
Example #19
0
        static bool?CompileCore(IBuildEngine engine, CecilTypeSystem typeSystem,
                                string projectDirectory, bool verifyIl,
                                MessageImportance logImportance
                                , bool debuggerLaunch = false)
        {
            if (debuggerLaunch)
            {
                // According this https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.debugger.launch?view=net-6.0#remarks
                // documentation, on not windows platform Debugger.Launch() always return true without running a debugger.
                if (System.Diagnostics.Debugger.Launch())
                {
                    // Set timeout at 1 minut.
                    var time    = new System.Diagnostics.Stopwatch();
                    var timeout = TimeSpan.FromMinutes(1);
                    time.Start();

                    // wait for the debugger to be attacked or timeout.
                    while (!System.Diagnostics.Debugger.IsAttached && time.Elapsed < timeout)
                    {
                        engine.LogMessage($"[PID:{System.Diagnostics.Process.GetCurrentProcess().Id}] Wating attach debugger. Elapsed {time.Elapsed}...", MessageImportance.High);
                        System.Threading.Thread.Sleep(100);
                    }

                    time.Stop();
                    if (time.Elapsed >= timeout)
                    {
                        engine.LogMessage("Wating attach debugger timeout.", MessageImportance.Normal);
                    }
                }
                else
                {
                    engine.LogMessage("Debugging cancelled.", MessageImportance.Normal);
                }
            }
            var asm    = typeSystem.TargetAssemblyDefinition;
            var emres  = new EmbeddedResources(asm);
            var avares = new AvaloniaResources(asm, projectDirectory);

            if (avares.Resources.Count(CheckXamlName) == 0 && emres.Resources.Count(CheckXamlName) == 0)
            {
                // Nothing to do
                return(null);
            }

            var clrPropertiesDef = new TypeDefinition("CompiledAvaloniaXaml", "XamlIlHelpers",
                                                      TypeAttributes.Class, asm.MainModule.TypeSystem.Object);

            asm.MainModule.Types.Add(clrPropertiesDef);
            var indexerAccessorClosure = new TypeDefinition("CompiledAvaloniaXaml", "!IndexerAccessorFactoryClosure",
                                                            TypeAttributes.Class, asm.MainModule.TypeSystem.Object);

            asm.MainModule.Types.Add(indexerAccessorClosure);
            var trampolineBuilder = new TypeDefinition("CompiledAvaloniaXaml", "XamlIlTrampolines",
                                                       TypeAttributes.Class, asm.MainModule.TypeSystem.Object);

            asm.MainModule.Types.Add(trampolineBuilder);

            var(xamlLanguage, emitConfig) = AvaloniaXamlIlLanguage.Configure(typeSystem);
            var compilerConfig = new AvaloniaXamlIlCompilerConfiguration(typeSystem,
                                                                         typeSystem.TargetAssembly,
                                                                         xamlLanguage,
                                                                         XamlXmlnsMappings.Resolve(typeSystem, xamlLanguage),
                                                                         AvaloniaXamlIlLanguage.CustomValueConverter,
                                                                         new XamlIlClrPropertyInfoEmitter(typeSystem.CreateTypeBuilder(clrPropertiesDef)),
                                                                         new XamlIlPropertyInfoAccessorFactoryEmitter(typeSystem.CreateTypeBuilder(indexerAccessorClosure)),
                                                                         new XamlIlTrampolineBuilder(typeSystem.CreateTypeBuilder(trampolineBuilder)),
                                                                         new DeterministicIdGenerator());


            var contextDef = new TypeDefinition("CompiledAvaloniaXaml", "XamlIlContext",
                                                TypeAttributes.Class, asm.MainModule.TypeSystem.Object);

            asm.MainModule.Types.Add(contextDef);

            var contextClass = XamlILContextDefinition.GenerateContextClass(typeSystem.CreateTypeBuilder(contextDef), typeSystem,
                                                                            xamlLanguage, emitConfig);

            var compiler = new AvaloniaXamlIlCompiler(compilerConfig, emitConfig, contextClass)
            {
                EnableIlVerification = verifyIl
            };

            var editorBrowsableAttribute = typeSystem
                                           .GetTypeReference(typeSystem.FindType("System.ComponentModel.EditorBrowsableAttribute"))
                                           .Resolve();
            var editorBrowsableCtor =
                asm.MainModule.ImportReference(editorBrowsableAttribute.GetConstructors()
                                               .First(c => c.Parameters.Count == 1));

            var runtimeHelpers = typeSystem.GetType("Avalonia.Markup.Xaml.XamlIl.Runtime.XamlIlRuntimeHelpers");
            var createRootServiceProviderMethod = asm.MainModule.ImportReference(
                typeSystem.GetTypeReference(runtimeHelpers).Resolve().Methods
                .First(x => x.Name == "CreateRootServiceProviderV2"));

            var loaderDispatcherDef = new TypeDefinition("CompiledAvaloniaXaml", "!XamlLoader",
                                                         TypeAttributes.Class, asm.MainModule.TypeSystem.Object);


            loaderDispatcherDef.CustomAttributes.Add(new CustomAttribute(editorBrowsableCtor)
            {
                ConstructorArguments = { new CustomAttributeArgument(editorBrowsableCtor.Parameters[0].ParameterType, 1) }
            });


            var loaderDispatcherMethod = new MethodDefinition("TryLoad",
                                                              MethodAttributes.Static | MethodAttributes.Public,
                                                              asm.MainModule.TypeSystem.Object)
            {
                Parameters = { new ParameterDefinition(asm.MainModule.TypeSystem.String) }
            };

            loaderDispatcherDef.Methods.Add(loaderDispatcherMethod);
            asm.MainModule.Types.Add(loaderDispatcherDef);

            var stringEquals = asm.MainModule.ImportReference(asm.MainModule.TypeSystem.String.Resolve().Methods.First(
                                                                  m =>
                                                                  m.IsStatic && m.Name == "Equals" && m.Parameters.Count == 2 &&
                                                                  m.ReturnType.FullName == "System.Boolean" &&
                                                                  m.Parameters[0].ParameterType.FullName == "System.String" &&
                                                                  m.Parameters[1].ParameterType.FullName == "System.String"));

            bool CompileGroup(IResourceGroup group)
            {
                var typeDef = new TypeDefinition("CompiledAvaloniaXaml", "!" + group.Name,
                                                 TypeAttributes.Class, asm.MainModule.TypeSystem.Object);

                typeDef.CustomAttributes.Add(new CustomAttribute(editorBrowsableCtor)
                {
                    ConstructorArguments = { new CustomAttributeArgument(editorBrowsableCtor.Parameters[0].ParameterType, 1) }
                });
                asm.MainModule.Types.Add(typeDef);
                var builder = typeSystem.CreateTypeBuilder(typeDef);

                foreach (var res in group.Resources.Where(CheckXamlName).OrderBy(x => x.FilePath.ToLowerInvariant()))
                {
                    try
                    {
                        engine.LogMessage($"XAMLIL: {res.Name} -> {res.Uri}", logImportance);

                        // StreamReader is needed here to handle BOM
                        var xaml   = new StreamReader(new MemoryStream(res.FileContents)).ReadToEnd();
                        var parsed = XDocumentXamlParser.Parse(xaml);

                        var initialRoot = (XamlAstObjectNode)parsed.Root;


                        var precompileDirective = initialRoot.Children.OfType <XamlAstXmlDirective>()
                                                  .FirstOrDefault(d => d.Namespace == XamlNamespaces.Xaml2006 && d.Name == "Precompile");
                        if (precompileDirective != null)
                        {
                            var precompileText = (precompileDirective.Values[0] as XamlAstTextNode)?.Text.Trim()
                                                 .ToLowerInvariant();
                            if (precompileText == "false")
                            {
                                continue;
                            }
                            if (precompileText != "true")
                            {
                                throw new XamlParseException("Invalid value for x:Precompile", precompileDirective);
                            }
                        }

                        var classDirective = initialRoot.Children.OfType <XamlAstXmlDirective>()
                                             .FirstOrDefault(d => d.Namespace == XamlNamespaces.Xaml2006 && d.Name == "Class");
                        IXamlType classType = null;
                        if (classDirective != null)
                        {
                            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 XamlParseException($"Unable to find type `{tn.Text}`", classDirective);
                            }
                            compiler.OverrideRootType(parsed,
                                                      new XamlAstClrTypeReference(classDirective, classType, false));
                            initialRoot.Children.Remove(classDirective);
                        }


                        compiler.Transform(parsed);
                        var populateName = classType == null ? "Populate:" + res.Name : "!XamlIlPopulate";
                        var buildName    = classType == null ? "Build:" + res.Name : null;

                        var classTypeDefinition =
                            classType == null ? null : typeSystem.GetTypeReference(classType).Resolve();


                        var populateBuilder = classTypeDefinition == null ?
                                              builder :
                                              typeSystem.CreateTypeBuilder(classTypeDefinition);
                        compiler.Compile(parsed,
                                         contextClass,
                                         compiler.DefinePopulateMethod(populateBuilder, parsed, populateName,
                                                                       classTypeDefinition == null),
                                         buildName == null ? null : compiler.DefineBuildMethod(builder, parsed, buildName, true),
                                         builder.DefineSubType(compilerConfig.WellKnownTypes.Object, "NamespaceInfo:" + res.Name,
                                                               true),
                                         (closureName, closureBaseType) =>
                                         populateBuilder.DefineSubType(closureBaseType, closureName, false),
                                         (closureName, returnType, parameterTypes) =>
                                         populateBuilder.DefineDelegateSubType(closureName, false, returnType, parameterTypes),
                                         res.Uri, res
                                         );


                        if (classTypeDefinition != null)
                        {
                            var compiledPopulateMethod = typeSystem.GetTypeReference(populateBuilder).Resolve()
                                                         .Methods.First(m => m.Name == populateName);

                            var designLoaderFieldType = typeSystem
                                                        .GetType("System.Action`1")
                                                        .MakeGenericType(typeSystem.GetType("System.Object"));

                            var designLoaderFieldTypeReference = (GenericInstanceType)typeSystem.GetTypeReference(designLoaderFieldType);
                            designLoaderFieldTypeReference.GenericArguments[0] =
                                asm.MainModule.ImportReference(designLoaderFieldTypeReference.GenericArguments[0]);
                            designLoaderFieldTypeReference = (GenericInstanceType)
                                                             asm.MainModule.ImportReference(designLoaderFieldTypeReference);

                            var designLoaderLoad =
                                typeSystem.GetMethodReference(
                                    designLoaderFieldType.Methods.First(m => m.Name == "Invoke"));
                            designLoaderLoad =
                                asm.MainModule.ImportReference(designLoaderLoad);
                            designLoaderLoad.DeclaringType = designLoaderFieldTypeReference;

                            var designLoaderField = new FieldDefinition("!XamlIlPopulateOverride",
                                                                        FieldAttributes.Static | FieldAttributes.Private, designLoaderFieldTypeReference);
                            classTypeDefinition.Fields.Add(designLoaderField);

                            const string TrampolineName = "!XamlIlPopulateTrampoline";
                            var          trampoline     = new MethodDefinition(TrampolineName,
                                                                               MethodAttributes.Static | MethodAttributes.Private, asm.MainModule.TypeSystem.Void);
                            trampoline.Parameters.Add(new ParameterDefinition(classTypeDefinition));
                            classTypeDefinition.Methods.Add(trampoline);

                            var regularStart = Instruction.Create(OpCodes.Call, createRootServiceProviderMethod);

                            trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ldsfld, designLoaderField));
                            trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Brfalse, regularStart));
                            trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ldsfld, designLoaderField));
                            trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0));
                            trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Call, designLoaderLoad));
                            trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));

                            trampoline.Body.Instructions.Add(regularStart);
                            trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0));
                            trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Call, compiledPopulateMethod));
                            trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
                            CopyDebugDocument(trampoline, compiledPopulateMethod);

                            var foundXamlLoader = false;
                            // Find AvaloniaXamlLoader.Load(this) and replace it with !XamlIlPopulateTrampoline(this)
                            foreach (var method in classTypeDefinition.Methods
                                     .Where(m => !m.Attributes.HasFlag(MethodAttributes.Static)))
                            {
                                var i = method.Body.Instructions;
                                for (var c = 1; c < i.Count; c++)
                                {
                                    if (i[c].OpCode == OpCodes.Call)
                                    {
                                        var op = i[c].Operand as MethodReference;

                                        // TODO: Throw an error
                                        // This usually happens when the same XAML resource was added twice for some weird reason
                                        // We currently support it for dual-named default theme resources
                                        if (op != null &&
                                            op.Name == TrampolineName)
                                        {
                                            foundXamlLoader = true;
                                            break;
                                        }
                                        if (op != null &&
                                            op.Name == "Load" &&
                                            op.Parameters.Count == 1 &&
                                            op.Parameters[0].ParameterType.FullName == "System.Object" &&
                                            op.DeclaringType.FullName == "Avalonia.Markup.Xaml.AvaloniaXamlLoader")
                                        {
                                            if (MatchThisCall(i, c - 1))
                                            {
                                                i[c].Operand    = trampoline;
                                                foundXamlLoader = true;
                                            }
                                        }
                                    }
                                }
                            }

                            if (!foundXamlLoader)
                            {
                                var ctors = classTypeDefinition.GetConstructors()
                                            .Where(c => !c.IsStatic).ToList();
                                // We can inject xaml loader into default constructor
                                if (ctors.Count == 1 && ctors[0].Body.Instructions.Count(o => o.OpCode != OpCodes.Nop) == 3)
                                {
                                    var i      = ctors[0].Body.Instructions;
                                    var retIdx = i.IndexOf(i.Last(x => x.OpCode == OpCodes.Ret));
                                    i.Insert(retIdx, Instruction.Create(OpCodes.Call, trampoline));
                                    i.Insert(retIdx, Instruction.Create(OpCodes.Ldarg_0));
                                }
                                else
                                {
                                    throw new InvalidProgramException(
                                              $"No call to AvaloniaXamlLoader.Load(this) call found anywhere in the type {classType.FullName} and type seems to have custom constructors.");
                                }
                            }
                        }

                        if (buildName != null || classTypeDefinition != null)
                        {
                            var compiledBuildMethod = buildName == null ?
                                                      null :
                                                      typeSystem.GetTypeReference(builder).Resolve()
                                                      .Methods.First(m => m.Name == buildName);
                            var parameterlessConstructor = compiledBuildMethod != null ?
                                                           null :
                                                           classTypeDefinition.GetConstructors().FirstOrDefault(c =>
                                                                                                                c.IsPublic && !c.IsStatic && !c.HasParameters);

                            if (compiledBuildMethod != null || parameterlessConstructor != null)
                            {
                                var i   = loaderDispatcherMethod.Body.Instructions;
                                var nop = Instruction.Create(OpCodes.Nop);
                                i.Add(Instruction.Create(OpCodes.Ldarg_0));
                                i.Add(Instruction.Create(OpCodes.Ldstr, res.Uri));
                                i.Add(Instruction.Create(OpCodes.Call, stringEquals));
                                i.Add(Instruction.Create(OpCodes.Brfalse, nop));
                                if (parameterlessConstructor != null)
                                {
                                    i.Add(Instruction.Create(OpCodes.Newobj, parameterlessConstructor));
                                }
                                else
                                {
                                    i.Add(Instruction.Create(OpCodes.Call, createRootServiceProviderMethod));
                                    i.Add(Instruction.Create(OpCodes.Call, compiledBuildMethod));
                                }

                                i.Add(Instruction.Create(OpCodes.Ret));
                                i.Add(nop);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        int lineNumber = 0, linePosition = 0;
                        if (e is XamlParseException xe)
                        {
                            lineNumber   = xe.LineNumber;
                            linePosition = xe.LinePosition;
                        }
                        engine.LogErrorEvent(new BuildErrorEventArgs("Avalonia", "XAMLIL", res.FilePath,
                                                                     lineNumber, linePosition, lineNumber, linePosition,
                                                                     e.Message, "", "Avalonia"));
                        return(false);
                    }
                    res.Remove();
                }


                // Technically that's a hack, but it fixes corert incompatibility caused by deterministic builds
                int dupeCounter = 1;

                foreach (var grp in typeDef.NestedTypes.GroupBy(x => x.Name))
                {
                    if (grp.Count() > 1)
                    {
                        foreach (var dupe in grp)
                        {
                            dupe.Name += "_dup" + dupeCounter++;
                        }
                    }
                }


                return(true);
            }

            if (emres.Resources.Count(CheckXamlName) != 0)
            {
                if (!CompileGroup(emres))
                {
                    return(false);
                }
            }
            if (avares.Resources.Count(CheckXamlName) != 0)
            {
                if (!CompileGroup(avares))
                {
                    return(false);
                }
                avares.Save();
            }

            loaderDispatcherMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Ldnull));
            loaderDispatcherMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
            return(true);
        }
Example #20
0
 public static string GetFqn(this IXamlType type) => $"{type.Assembly?.Name}:{type.Namespace}.{type.Name}";
Example #21
0
 public TypeReference GetTypeReference(IXamlType t) => ((ITypeReference)t).Reference;
Example #22
0
 public static bool IsNullableOf(this IXamlType type, IXamlType vtype)
 {
     return(type.IsNullable() && type.GenericArguments[0].Equals(vtype));
 }
Example #23
0
 public XamlIlSelectorInitialNode(IXamlLineInfo info,
                                  IXamlType selectorType) : base(null, info, selectorType)
 {
 }
Example #24
0
 public static IXamlType MakeGenericType(this IXamlType type, params IXamlType[] typeArguments)
 => type.MakeGenericType(typeArguments);
Example #25
0
 public XamlIlOrSelectorNode(IXamlLineInfo info, IXamlType selectorType) : base(null, info, selectorType)
 {
 }
Example #26
0
        private XamlILContextDefinition(IXamlTypeBuilder <IXamlILEmitter> parentBuilder,
                                        IXamlTypeSystem typeSystem, XamlLanguageTypeMappings mappings,
                                        XamlLanguageEmitMappings <IXamlILEmitter, XamlILNodeEmitResult> emitMappings)
        {
            var so      = typeSystem.GetType("System.Object");
            var builder = parentBuilder.DefineSubType(so, "Context", true);

            builder.DefineGenericParameters(new[]
            {
                new KeyValuePair <string, XamlGenericParameterConstraint>("TTarget",
                                                                          new XamlGenericParameterConstraint
                {
                    IsClass = true
                })
            });
            var rootObjectField             = builder.DefineField(builder.GenericParameters[0], "RootObject", true, false);
            var intermediateRootObjectField = builder.DefineField(so, XamlRuntimeContextDefintion.IntermediateRootObjectFieldName, true, false);

            _parentServiceProviderField = builder.DefineField(mappings.ServiceProvider, "_sp", false, false);
            if (mappings.InnerServiceProviderFactoryMethod != null)
            {
                _innerServiceProviderField = builder.DefineField(mappings.ServiceProvider, "_innerSp", false, false);
            }

            var staticProvidersField = builder.DefineField(typeSystem.GetType("System.Object").MakeArrayType(1),
                                                           "_staticProviders", false, false);


            var systemType   = typeSystem.GetType("System.Type");
            var systemUri    = typeSystem.GetType("System.Uri");
            var systemString = typeSystem.GetType("System.String");
            var getServiceInterfaceMethod = mappings.ServiceProvider.FindMethod("GetService", so, false, systemType);

            var ownServices   = new List <IXamlType>();
            var ctorCallbacks = new List <Action <IXamlILEmitter> >();

            if (mappings.RootObjectProvider != null)
            {
                builder.AddInterfaceImplementation(mappings.RootObjectProvider);
                var rootGen = ImplementInterfacePropertyGetter(builder, mappings.RootObjectProvider, XamlRuntimeContextDefintion.RootObjectFieldName)
                              .Generator;
                var tryParent          = rootGen.DefineLabel();
                var fail               = rootGen.DefineLabel();
                var parentRootProvider = rootGen.DefineLocal(mappings.RootObjectProvider);
                rootGen
                // if(RootObject!=null) return RootObject;
                .LdThisFld(rootObjectField)
                .Box(rootObjectField.FieldType)
                .Brfalse(tryParent)
                .LdThisFld(rootObjectField)
                .Box(rootObjectField.FieldType)
                .Ret()
                // if(_sp == null) goto fail;
                .MarkLabel(tryParent)
                .LdThisFld(_parentServiceProviderField)
                .Brfalse(fail)
                // parentProv =  (IRootObjectProvider)_sp.GetService(typeof(IRootObjectProvider));
                .LdThisFld(_parentServiceProviderField)
                .Ldtype(mappings.RootObjectProvider)
                .EmitCall(getServiceInterfaceMethod)
                .Castclass(mappings.RootObjectProvider)
                .Stloc(parentRootProvider)
                // if(parentProv == null) goto fail;
                .Ldloc(parentRootProvider)
                .Brfalse(fail)
                // return parentProv.Root;
                .Ldloc(parentRootProvider)
                .EmitCall(mappings.RootObjectProvider.FindMethod(m => m.Name == "get_RootObject"))
                .Ret()
                // fail:
                .MarkLabel(fail)
                .Ldnull()
                .Ret();

                if (mappings.RootObjectProviderIntermediateRootPropertyName != null)
                {
                    ImplementInterfacePropertyGetter(builder, mappings.RootObjectProvider, mappings.RootObjectProviderIntermediateRootPropertyName)
                    .Generator
                    .LdThisFld(intermediateRootObjectField)
                    .Ret();
                }

                ownServices.Add(mappings.RootObjectProvider);
            }

            if (mappings.ParentStackProvider != null)
            {
                builder.AddInterfaceImplementation(mappings.ParentStackProvider);
                var objectListType = typeSystem.GetType("System.Collections.Generic.List`1")
                                     .MakeGenericType(new[] { typeSystem.GetType("System.Object") });
                ParentListField = builder.DefineField(objectListType, XamlRuntimeContextDefintion.ParentListFieldName, true, false);

                var enumerator = EmitParentEnumerable(typeSystem, parentBuilder, mappings);
                CreateCallbacks.Add(enumerator.createCallback);
                var parentStackEnumerableField = builder.DefineField(
                    typeSystem.GetType("System.Collections.Generic.IEnumerable`1").MakeGenericType(new[] { so }),
                    "_parentStackEnumerable", false, false);

                ImplementInterfacePropertyGetter(builder, mappings.ParentStackProvider, "Parents")
                .Generator.LdThisFld(parentStackEnumerableField).Ret();

                ctorCallbacks.Add(g => g
                                  .Emit(OpCodes.Ldarg_0)
                                  .Emit(OpCodes.Newobj, objectListType.FindConstructor(new List <IXamlType>()))
                                  .Emit(OpCodes.Stfld, ParentListField)
                                  .Emit(OpCodes.Ldarg_0)
                                  .LdThisFld(ParentListField)
                                  .LdThisFld(_parentServiceProviderField)
                                  .Emit(OpCodes.Newobj, enumerator.ctor)
                                  .Emit(OpCodes.Stfld, parentStackEnumerableField));
                ownServices.Add(mappings.ParentStackProvider);
            }

            ownServices.Add(EmitTypeDescriptorContextStub(typeSystem, builder, mappings));

            if (mappings.ProvideValueTarget != null)
            {
                builder.AddInterfaceImplementation(mappings.ProvideValueTarget);
                PropertyTargetObject   = builder.DefineField(so, XamlRuntimeContextDefintion.ProvideTargetObjectName, true, false);
                PropertyTargetProperty = builder.DefineField(so, XamlRuntimeContextDefintion.ProvideTargetPropertyName, true, false);
                ImplementInterfacePropertyGetter(builder, mappings.ProvideValueTarget, "TargetObject")
                .Generator.LdThisFld(PropertyTargetObject).Ret();
                ImplementInterfacePropertyGetter(builder, mappings.ProvideValueTarget, "TargetProperty")
                .Generator.LdThisFld(PropertyTargetProperty).Ret();
                ownServices.Add(mappings.ProvideValueTarget);
            }

            IXamlField baseUriField = null;

            if (mappings.UriContextProvider != null)
            {
                baseUriField = builder.DefineField(systemUri, "_baseUri", false, false);
                builder.AddInterfaceImplementation(mappings.UriContextProvider);
                var getter = builder.DefineMethod(systemUri, new IXamlType[0], "get_BaseUri", true, false, true);
                var setter = builder.DefineMethod(typeSystem.GetType("System.Void"), new[] { systemUri },
                                                  "set_BaseUri", true, false, true);

                getter.Generator
                .LdThisFld(baseUriField)
                .Ret();

                setter.Generator
                .Ldarg_0()
                .Ldarg(1)
                .Stfld(baseUriField)
                .Ret();
                builder.DefineProperty(systemUri, "BaseUri", setter, getter);


                ownServices.Add(mappings.UriContextProvider);
            }

            builder.AddInterfaceImplementation(mappings.ServiceProvider);
            var getServiceMethod = builder.DefineMethod(so,
                                                        new[] { systemType },
                                                        "GetService", true, false, true);

            ownServices = ownServices.Where(s => s != null).ToList();


            if (_innerServiceProviderField != null)
            {
                var next        = getServiceMethod.Generator.DefineLabel();
                var innerResult = getServiceMethod.Generator.DefineLocal(so);
                getServiceMethod.Generator
                //if(_inner == null) goto next;
                .LdThisFld(_innerServiceProviderField)
                .Brfalse(next)
                // var innerRes = _inner.GetService(type);
                .LdThisFld(_innerServiceProviderField)
                .Ldarg(1)
                .EmitCall(getServiceInterfaceMethod)
                .Stloc(innerResult)
                // if(innerRes == null) goto next;
                .Ldloc(innerResult)
                .Brfalse(next)
                // return innerRes
                .Ldloc(innerResult)
                .Ret()
                .MarkLabel(next);
            }
            var compare = systemType.FindMethod("Equals", typeSystem.GetType("System.Boolean"),
                                                false, systemType);
            var isAssignableFrom = systemType.FindMethod("IsAssignableFrom", typeSystem.GetType("System.Boolean"),
                                                         false, systemType);
            var fromHandle        = systemType.Methods.First(m => m.Name == "GetTypeFromHandle");
            var getTypeFromObject = so.Methods.First(m => m.Name == "GetType" && m.Parameters.Count == 0);

            if (ownServices.Count != 0)
            {
                for (var c = 0; c < ownServices.Count; c++)
                {
                    var next = getServiceMethod.Generator.DefineLabel();
                    getServiceMethod.Generator
                    .Emit(OpCodes.Ldtoken, ownServices[c])
                    .EmitCall(fromHandle)
                    .Emit(OpCodes.Ldarg_1)
                    .Emit(OpCodes.Callvirt, compare)
                    .Emit(OpCodes.Brfalse, next)
                    .Emit(OpCodes.Ldarg_0)
                    .Emit(OpCodes.Ret)
                    .MarkLabel(next);
                }
            }

            var staticProviderIndex   = getServiceMethod.Generator.DefineLocal(typeSystem.GetType("System.Int32"));
            var staticProviderNext    = getServiceMethod.Generator.DefineLabel();
            var staticProviderFailed  = getServiceMethod.Generator.DefineLabel();
            var staticProviderEnd     = getServiceMethod.Generator.DefineLabel();
            var staticProviderElement = getServiceMethod.Generator.DefineLocal(so);

            getServiceMethod.Generator
            //start: if(_staticProviders == null) goto: end
            .LdThisFld(staticProvidersField)
            .Brfalse(staticProviderEnd)
            // var c = 0
            .Ldc_I4(0)
            .Stloc(staticProviderIndex)
            // next:
            .MarkLabel(staticProviderNext)
            // if(c >= _staticProviders.Length) goto: end
            .Ldloc(staticProviderIndex)
            .LdThisFld(staticProvidersField)
            .Ldlen()
            .Bge(staticProviderEnd)
            // var obj = _staticProviders[c]
            .LdThisFld(staticProvidersField)
            .Ldloc(staticProviderIndex)
            .Ldelem_ref()
            // dup
            .Stloc(staticProviderElement)
            .Ldarg(1)
            .Ldloc(staticProviderElement)
            // if(obj.GetType().Equals(arg1)) return obj; else goto failed;
            .EmitCall(getTypeFromObject)
            .EmitCall(isAssignableFrom)
            .Brfalse(staticProviderFailed)
            .Ldloc(staticProviderElement)
            .Ret()
            // failed:
            .MarkLabel(staticProviderFailed)
            // c++
            .Ldloc(staticProviderIndex)
            .Ldc_I4(1)
            .Add()
            .Stloc(staticProviderIndex)
            // goto: start
            .Br(staticProviderNext)
            // end:
            .MarkLabel(staticProviderEnd);

            var noParentProvider = getServiceMethod.Generator.DefineLabel();

            getServiceMethod.Generator
            .LdThisFld(_parentServiceProviderField)
            .Brfalse(noParentProvider)
            .LdThisFld(_parentServiceProviderField)
            .Ldarg(1)
            .EmitCall(getServiceInterfaceMethod)
            .Emit(OpCodes.Ret)
            .MarkLabel(noParentProvider)
            .Ldnull()
            .Ret();

            var ctor = builder.DefineConstructor(false,
                                                 mappings.ServiceProvider,
                                                 staticProvidersField.FieldType,
                                                 systemString);

            ctor.Generator
            .Emit(OpCodes.Ldarg_0)
            .Emit(OpCodes.Call, so.Constructors.First())
            .Emit(OpCodes.Ldarg_0)
            .Emit(OpCodes.Ldarg_1)
            .Emit(OpCodes.Stfld, _parentServiceProviderField)
            .Emit(OpCodes.Ldarg_0)
            .Emit(OpCodes.Ldarg_2)
            .Emit(OpCodes.Stfld, staticProvidersField);
            if (baseUriField != null)
            {
                var noUri = ctor.Generator.DefineLabel();
                ctor.Generator
                .Emit(OpCodes.Ldarg_3)
                .Brfalse(noUri)
                .Emit(OpCodes.Ldarg_0)
                .Emit(OpCodes.Ldarg_3)
                .Newobj(systemUri.FindConstructor(new List <IXamlType>
                {
                    typeSystem.GetType("System.String")
                }))
                .Emit(OpCodes.Stfld, baseUriField)
                .MarkLabel(noUri);
            }

            foreach (var feature in ctorCallbacks)
            {
                feature(ctor.Generator);
            }

            emitMappings.ContextTypeBuilderCallback?.Invoke(builder, ctor.Generator);

            // We are calling this last to ensure that our own services are ready
            if (_innerServiceProviderField != null)
            {
                ctor.Generator
                // _innerSp = InnerServiceProviderFactory(this)
                .Ldarg_0()
                .Ldarg_0()
                .EmitCall(mappings.InnerServiceProviderFactoryMethod)
                .Stfld(_innerServiceProviderField);
            }

            ctor.Generator.Emit(OpCodes.Ret);

            Constructor = ctor;
            CreateCallbacks.Add(() => { parentBuilder.CreateType(); });

            if (ParentListField != null)
            {
                EmitPushPopParent(builder, typeSystem);
            }

            CreateAllTypes();
            ContextType = builder.CreateType();
        }
Example #27
0
 public XamlUserType(XamlTypeInfoProvider provider, string fullName, Type fullType, IXamlType baseType)
     : base(fullName, fullType)
 {
     _provider = provider;
     _baseType = baseType;
 }
Example #28
0
 public BindingSetter(AvaloniaXamlIlWellKnownTypes types,
                      IXamlType declaringType,
                      IXamlField avaloniaProperty) : base(types, declaringType, avaloniaProperty)
 {
     Parameters = new[] { types.IBinding };
 }
Example #29
0
        public static IXamlType UpdateCompiledBindingExtension(AstTransformationContext context, XamlAstConstructableObjectNode binding, Func <IXamlType> startTypeResolver, IXamlType selfType)
        {
            IXamlType bindingResultType = null;

            if (binding.Arguments.Count > 0 && binding.Arguments[0] is ParsedBindingPathNode bindingPath)
            {
                var transformed = TransformBindingPath(
                    context,
                    bindingPath,
                    startTypeResolver,
                    selfType,
                    bindingPath.Path);

                bindingResultType    = transformed.BindingResultType;
                binding.Arguments[0] = transformed;
            }
            else
            {
                var bindingPathAssignment = binding.Children.OfType <XamlPropertyAssignmentNode>()
                                            .FirstOrDefault(v => v.Property.Name == "Path");

                if (bindingPathAssignment is null)
                {
                    return(startTypeResolver());
                }

                if (bindingPathAssignment.Values[0] is ParsedBindingPathNode bindingPathNode)
                {
                    var transformed = TransformBindingPath(
                        context,
                        bindingPathNode,
                        startTypeResolver,
                        selfType,
                        bindingPathNode.Path);

                    bindingResultType = transformed.BindingResultType;
                    bindingPathAssignment.Values[0] = transformed;
                }
                else
                {
                    throw new InvalidOperationException();
                }
            }

            return(bindingResultType);
        }
Example #30
0
 public UnsetValueSetter(AvaloniaXamlIlWellKnownTypes types, IXamlType declaringType, IXamlField avaloniaProperty)
     : base(types, declaringType, avaloniaProperty)
 {
     Parameters = new[] { types.UnsetValueType };
 }
Example #31
0
 public XamlUserType(XamlTypeInfoProvider provider, string fullName, Type fullType, IXamlType baseType)
     : base(fullName, fullType)
 {
     _provider = provider;
     _baseType = baseType;
 }
Example #32
0
 public IXamlCustomAttribute GetCustomAttribute(IXamlProperty property, IXamlType attributeType)
 {
     return(null);
 }