Browse Source

FontFamily and TimeSpan intrinsics

Nikita Tsukanov 5 years ago
parent
commit
ee470af59a

+ 43 - 0
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AstNodes/AvaloniaXamlIlFontFamilyAstNode.cs

@@ -0,0 +1,43 @@
+using System;
+using System.Collections.Generic;
+using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers;
+using XamlX.Ast;
+using XamlX.Emit;
+using XamlX.IL;
+using XamlX.TypeSystem;
+
+namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.AstNodes
+{
+    class AvaloniaXamlIlFontFamilyAstNode: XamlAstNode, IXamlAstValueNode, IXamlAstILEmitableNode
+    {
+        private readonly AvaloniaXamlIlWellKnownTypes _types;
+        private readonly string _text;
+
+        public IXamlAstTypeReference Type { get; }
+        
+        public AvaloniaXamlIlFontFamilyAstNode(AvaloniaXamlIlWellKnownTypes types,
+            string text,
+            IXamlLineInfo lineInfo) : base(lineInfo)
+        {
+            _types = types;
+            _text = text;
+            Type = new XamlAstClrTypeReference(lineInfo, types.FontFamily, false);
+        }
+        
+        public XamlILNodeEmitResult Emit(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen)
+        {
+            codeGen
+                .Ldloc(context.ContextLocal)
+                .Castclass(context.Configuration.TypeMappings.UriContextProvider)
+                .EmitCall(context.Configuration.TypeMappings.UriContextProvider.FindMethod(
+                    "get_BaseUri", _types.Uri, false))
+                .Ldstr(_text)
+                .Newobj(_types.FontFamilyConstructorUriName);
+            return XamlILNodeEmitResult.Type(0, _types.FontFamily);
+        }
+
+        
+
+        
+    }
+}

+ 38 - 13
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguage.cs

@@ -1,6 +1,8 @@
+using System;
 using System.Collections.Generic;
 using System.Globalization;
 using System.Linq;
+using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.AstNodes;
 using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers;
 using XamlX;
 using XamlX.Ast;
@@ -166,17 +168,41 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
         public static bool CustomValueConverter(AstTransformationContext context,
             IXamlAstValueNode node, IXamlType type, out IXamlAstValueNode result)
         {
-            if (type.FullName == "System.TimeSpan" 
-                && node is XamlAstTextNode tn
-                && !tn.Text.Contains(":"))
+            if (!(node is XamlAstTextNode textNode))
             {
-                var seconds = double.Parse(tn.Text, CultureInfo.InvariantCulture);
-                result = new XamlStaticOrTargetedReturnMethodCallNode(tn,
-                    type.FindMethod("FromSeconds", type, false, context.Configuration.WellKnownTypes.Double),
-                    new[]
-                    {
-                        new XamlConstantNode(tn, context.Configuration.WellKnownTypes.Double, seconds)
-                    });
+                result = null;
+                return false;
+            }
+
+            var text = textNode.Text;
+            
+            var types = context.GetAvaloniaTypes();
+
+            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;
             }
 
@@ -185,9 +211,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
                 var scope = context.ParentNodes().OfType<AvaloniaXamlIlTargetTypeMetadataNode>().FirstOrDefault();
                 if (scope == null)
                     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);
+
+                result = XamlIlAvaloniaPropertyHelper.CreateNode(context, text, scope.TargetType, node );
                 return true;
             }
 

+ 10 - 0
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs

@@ -1,3 +1,4 @@
+using System.Collections.Generic;
 using XamlX.Emit;
 using XamlX.IL;
 using XamlX.Transform;
@@ -47,6 +48,11 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
         public IXamlType ReflectionBindingExtension { get; }
 
         public IXamlType RelativeSource { get; }
+        public IXamlType Long { get; }
+        public IXamlType Uri { get; }
+        public IXamlType FontFamily { get; }
+        public IXamlConstructor FontFamilyConstructorUriName { get; }
+        
 
         public AvaloniaXamlIlWellKnownTypes(TransformerConfiguration cfg)
         {
@@ -104,6 +110,10 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
             ItemsRepeater = cfg.TypeSystem.GetType("Avalonia.Controls.ItemsRepeater");
             ReflectionBindingExtension = cfg.TypeSystem.GetType("Avalonia.Markup.Xaml.MarkupExtensions.ReflectionBindingExtension");
             RelativeSource = cfg.TypeSystem.GetType("Avalonia.Data.RelativeSource");
+            Long = cfg.TypeSystem.GetType("System.Int64");
+            Uri = cfg.TypeSystem.GetType("System.Uri");
+            FontFamily = cfg.TypeSystem.GetType("Avalonia.Media.FontFamily");
+            FontFamilyConstructorUriName = FontFamily.FindConstructor(new List<IXamlType> { Uri, XamlIlTypes.String });
         }
     }