From f14aac365bf6bc12b5d7133c22ce0ddd839fc0f2 Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Fri, 15 Feb 2019 14:48:10 +0300 Subject: [PATCH] WIP --- .gitmodules | 3 + .../Pages/ButtonSpinnerPage.xaml.cs | 2 +- .../UsableDuringInitializationAttribute.cs | 10 ++ .../Controls/NameScopeExtensions.cs | 3 +- src/Avalonia.Visuals/Visual.cs | 2 + .../Avalonia.Markup.Xaml.csproj | 18 ++ .../AvaloniaTypeConverters.cs | 1 + .../AvaloniaXamlLoader.cs | 15 +- .../AvaloniaPropertyTypeConverter.cs | 4 +- .../Converters/BitmapTypeConverter.cs | 4 +- .../Converters/FontFamilyTypeConverter.cs | 2 +- .../Converters/IconTypeConverter.cs | 2 +- src/Markup/Avalonia.Markup.Xaml/Extensions.cs | 47 +++++ .../MarkupExtensions/BindingExtension.cs | 11 +- .../DynamicResourceExtension.cs | 16 +- .../MarkupExtensions/ResourceInclude.cs | 2 +- .../MarkupExtensions/StyleIncludeExtension.cs | 5 +- .../PortableXaml/TypeDescriptorExtensions.cs | 4 +- .../XamlIl/AvaloniaXamlIlRuntimeCompiler.cs | 160 ++++++++++++++++++ .../AvaloniaPropertyDescriptorEmitter.cs | 21 +++ .../AvaloniaXamlIlCompiler.cs | 61 +++++++ .../AvaloniaXamlIlLanguage.cs | 153 +++++++++++++++++ .../XamlIl/CompilerExtensions/README.md | 4 + .../Transformers/AddNameScopeRegistration.cs | 79 +++++++++ .../IgnoredDirectivesTransformer.cs | 27 +++ .../KnownPseudoMarkupExtensionsTransformer.cs | 26 +++ .../Transformers/XNameTransformer.cs | 33 ++++ .../IAvaloniaXamlIlParentStackProvider.cs | 9 + ...valoniaXamlIlXmlNamespaceInfoProviderV1.cs | 15 ++ .../XamlIl/Runtime/XamlIlRuntimeHelpers.cs | 121 +++++++++++++ .../Avalonia.Markup.Xaml/XamlIl/xamlil.github | 1 + 31 files changed, 827 insertions(+), 34 deletions(-) create mode 100644 src/Avalonia.Base/Metadata/UsableDuringInitializationAttribute.cs create mode 100644 src/Markup/Avalonia.Markup.Xaml/Extensions.cs create mode 100644 src/Markup/Avalonia.Markup.Xaml/XamlIl/AvaloniaXamlIlRuntimeCompiler.cs create mode 100644 src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaPropertyDescriptorEmitter.cs create mode 100644 src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlCompiler.cs create mode 100644 src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlLanguage.cs create mode 100644 src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/README.md create mode 100644 src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AddNameScopeRegistration.cs create mode 100644 src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/IgnoredDirectivesTransformer.cs create mode 100644 src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/KnownPseudoMarkupExtensionsTransformer.cs create mode 100644 src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/XNameTransformer.cs create mode 100644 src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/IAvaloniaXamlIlParentStackProvider.cs create mode 100644 src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/IAvaloniaXamlIlXmlNamespaceInfoProviderV1.cs create mode 100644 src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs create mode 160000 src/Markup/Avalonia.Markup.Xaml/XamlIl/xamlil.github diff --git a/.gitmodules b/.gitmodules index 22c56307b0..22a241f120 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "nukebuild/Numerge"] path = nukebuild/Numerge url = https://github.com/kekekeks/Numerge.git +[submodule "src/Markup/Avalonia.Markup.Xaml/XamlIl/xamlil.github"] + path = src/Markup/Avalonia.Markup.Xaml/XamlIl/xamlil.github + url = https://github.com/kekekeks/XamlIl.git diff --git a/samples/ControlCatalog/Pages/ButtonSpinnerPage.xaml.cs b/samples/ControlCatalog/Pages/ButtonSpinnerPage.xaml.cs index 1f753ab3ea..c5042baccb 100644 --- a/samples/ControlCatalog/Pages/ButtonSpinnerPage.xaml.cs +++ b/samples/ControlCatalog/Pages/ButtonSpinnerPage.xaml.cs @@ -18,7 +18,7 @@ namespace ControlCatalog.Pages AvaloniaXamlLoader.Load(this); } - private void OnSpin(object sender, SpinEventArgs e) + public void OnSpin(object sender, SpinEventArgs e) { var spinner = (ButtonSpinner)sender; var txtBox = (TextBlock)spinner.Content; diff --git a/src/Avalonia.Base/Metadata/UsableDuringInitializationAttribute.cs b/src/Avalonia.Base/Metadata/UsableDuringInitializationAttribute.cs new file mode 100644 index 0000000000..753a96b9ce --- /dev/null +++ b/src/Avalonia.Base/Metadata/UsableDuringInitializationAttribute.cs @@ -0,0 +1,10 @@ +using System; + +namespace Avalonia.Metadata +{ + [AttributeUsage(AttributeTargets.Class)] + public class UsableDuringInitializationAttribute : Attribute + { + + } +} diff --git a/src/Avalonia.Styling/Controls/NameScopeExtensions.cs b/src/Avalonia.Styling/Controls/NameScopeExtensions.cs index 491e4d71a7..991a97a614 100644 --- a/src/Avalonia.Styling/Controls/NameScopeExtensions.cs +++ b/src/Avalonia.Styling/Controls/NameScopeExtensions.cs @@ -71,10 +71,11 @@ namespace Avalonia.Controls { Contract.Requires(control != null); - return control.GetSelfAndLogicalAncestors() + var scope = control.GetSelfAndLogicalAncestors() .OfType() .Select(x => (x as INameScope) ?? NameScope.GetNameScope(x)) .FirstOrDefault(x => x != null); + return scope; } } } diff --git a/src/Avalonia.Visuals/Visual.cs b/src/Avalonia.Visuals/Visual.cs index f26c21d1b6..3360ba84c1 100644 --- a/src/Avalonia.Visuals/Visual.cs +++ b/src/Avalonia.Visuals/Visual.cs @@ -9,6 +9,7 @@ using Avalonia.Collections; using Avalonia.Data; using Avalonia.Logging; using Avalonia.Media; +using Avalonia.Metadata; using Avalonia.Rendering; using Avalonia.VisualTree; @@ -23,6 +24,7 @@ namespace Avalonia /// to render the control. To traverse the visual tree, use the /// extension methods defined in . /// + [UsableDuringInitialization] public class Visual : StyledElement, IVisual { /// diff --git a/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj b/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj index 38d207a31d..4603d31fae 100644 --- a/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj +++ b/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj @@ -15,6 +15,7 @@ + @@ -50,8 +51,21 @@ + + + + + + + + + + + + + @@ -63,6 +77,10 @@ + + + + diff --git a/src/Markup/Avalonia.Markup.Xaml/AvaloniaTypeConverters.cs b/src/Markup/Avalonia.Markup.Xaml/AvaloniaTypeConverters.cs index c30822aacb..2b6572e1a2 100644 --- a/src/Markup/Avalonia.Markup.Xaml/AvaloniaTypeConverters.cs +++ b/src/Markup/Avalonia.Markup.Xaml/AvaloniaTypeConverters.cs @@ -29,6 +29,7 @@ namespace Avalonia.Markup.Xaml /// public static class AvaloniaTypeConverters { + // When adding item to that list make sure to modify AvaloniaXamlIlLanguage private static Dictionary _converters = new Dictionary() { { typeof(AvaloniaList<>), typeof(AvaloniaListConverter<>) }, diff --git a/src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs b/src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs index a825deeae3..dd413ee10f 100644 --- a/src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs +++ b/src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs @@ -13,6 +13,7 @@ using System.Reflection; using System.Runtime.Serialization; using System.Runtime.Serialization.Json; using System.Text; +using Avalonia.Markup.Xaml.XamlIl; namespace Avalonia.Markup.Xaml { @@ -23,6 +24,8 @@ namespace Avalonia.Markup.Xaml { private readonly AvaloniaXamlSchemaContext _context = GetContext(); + public bool EnforceCompilerForRuntimeXaml { get; set; } = true; + public bool IsDesignMode { get => _context.IsDesignMode; @@ -137,13 +140,13 @@ namespace Avalonia.Markup.Xaml using (var stream = asset.stream) { var absoluteUri = uri.IsAbsoluteUri ? uri : new Uri(baseUri, uri); - try + //try { return Load(stream, asset.assembly, rootInstance, absoluteUri); } - catch (Exception e) + //catch (Exception e) { - throw new XamlLoadException("Error loading xaml at " + absoluteUri + ": " + e.Message, e); + //throw new XamlLoadException("Error loading xaml at " + absoluteUri + ": " + e.Message, e); } } } @@ -179,6 +182,12 @@ namespace Avalonia.Markup.Xaml /// The loaded object. public object Load(Stream stream, Assembly localAssembly, object rootInstance = null, Uri uri = null) { + if (EnforceCompilerForRuntimeXaml) + { + return AvaloniaXamlIlRuntimeCompiler.Load(stream, localAssembly, rootInstance, uri); + } + + var readerSettings = new XamlXmlReaderSettings() { BaseUri = uri, diff --git a/src/Markup/Avalonia.Markup.Xaml/Converters/AvaloniaPropertyTypeConverter.cs b/src/Markup/Avalonia.Markup.Xaml/Converters/AvaloniaPropertyTypeConverter.cs index 8a0ba64582..18a7fe9ab6 100644 --- a/src/Markup/Avalonia.Markup.Xaml/Converters/AvaloniaPropertyTypeConverter.cs +++ b/src/Markup/Avalonia.Markup.Xaml/Converters/AvaloniaPropertyTypeConverter.cs @@ -28,8 +28,8 @@ namespace Avalonia.Markup.Xaml.Converters var parser = new PropertyParser(); var (ns, owner, propertyName) = parser.Parse(new CharacterReader(((string)value).AsSpan())); var ownerType = TryResolveOwnerByName(context, ns, owner); - var targetType = context.GetFirstAmbientValue()?.TargetType ?? - context.GetFirstAmbientValue