diff --git a/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj b/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj index 589f41c06b..804ca1f9b8 100644 --- a/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj +++ b/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj @@ -3,6 +3,7 @@ Exe netcoreapp2.0 + true diff --git a/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs b/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs index 851b37d302..05659389b1 100644 --- a/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs +++ b/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs @@ -258,8 +258,8 @@ namespace Avalonia.Build.Tasks int lineNumber = 0, linePosition = 0; if (e is XamlIlParseException xe) { - lineNumber = xe.Line; - linePosition = xe.Position; + lineNumber = xe.LineNumber; + linePosition = xe.LinePosition; } engine.LogErrorEvent(new BuildErrorEventArgs("Avalonia", "XAMLIL", res.FilePath, lineNumber, linePosition, lineNumber, linePosition, diff --git a/src/Avalonia.DesignerSupport/Remote/RemoteDesignerEntryPoint.cs b/src/Avalonia.DesignerSupport/Remote/RemoteDesignerEntryPoint.cs index 67a93f3c9c..801ed74ca0 100644 --- a/src/Avalonia.DesignerSupport/Remote/RemoteDesignerEntryPoint.cs +++ b/src/Avalonia.DesignerSupport/Remote/RemoteDesignerEntryPoint.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Net; using System.Reflection; +using System.Xml; using Avalonia.Controls; using Avalonia.Input; using Avalonia.Remote.Protocol; @@ -206,7 +207,8 @@ namespace Avalonia.DesignerSupport.Remote catch (Exception e) { var xamlException = e as XamlException; - + var xmlException = e as XmlException; + s_transport.Send(new UpdateXamlResultMessage { Error = e.ToString(), @@ -214,8 +216,8 @@ namespace Avalonia.DesignerSupport.Remote { ExceptionType = e.GetType().FullName, Message = e.Message.ToString(), - LineNumber = xamlException?.LineNumber, - LinePosition = xamlException?.LinePosition, + LineNumber = xamlException?.LineNumber ?? xmlException?.LineNumber, + LinePosition = xamlException?.LinePosition ?? xmlException?.LinePosition, } }); } diff --git a/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj b/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj index fe1c20eec9..a3d206edb7 100644 --- a/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj +++ b/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj @@ -56,6 +56,7 @@ + diff --git a/src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs b/src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs index a51390f5c7..717b2ed1e8 100644 --- a/src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs +++ b/src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs @@ -26,7 +26,7 @@ namespace Avalonia.Markup.Xaml { public bool IsDesignMode { get; set; } - public bool UseLegacyXamlLoader { get; set; } = false; + public static bool UseLegacyXamlLoader { get; set; } = false; /// /// Initializes a new instance of the class. @@ -176,7 +176,7 @@ namespace Avalonia.Markup.Xaml public object Load(Stream stream, Assembly localAssembly, object rootInstance = null, Uri uri = null) { if (!UseLegacyXamlLoader) - return AvaloniaXamlIlRuntimeCompiler.Load(stream, localAssembly, rootInstance, uri); + return AvaloniaXamlIlRuntimeCompiler.Load(stream, localAssembly, rootInstance, uri, IsDesignMode); var readerSettings = new XamlXmlReaderSettings() diff --git a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/ResourceInclude.cs b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/ResourceInclude.cs index 1f3d9fc139..827f58a909 100644 --- a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/ResourceInclude.cs +++ b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/ResourceInclude.cs @@ -54,6 +54,11 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions /// public override object ProvideValue(IServiceProvider serviceProvider) + { + return ProvideTypedValue(serviceProvider); + } + + public ResourceInclude ProvideTypedValue(IServiceProvider serviceProvider) { var tdc = (ITypeDescriptorContext)serviceProvider; _baseUri = tdc?.GetContextBaseUri(); diff --git a/src/Markup/Avalonia.Markup.Xaml/XamlIl/AvaloniaXamlIlRuntimeCompiler.cs b/src/Markup/Avalonia.Markup.Xaml/XamlIl/AvaloniaXamlIlRuntimeCompiler.cs index 621facea25..9c9418458a 100644 --- a/src/Markup/Avalonia.Markup.Xaml/XamlIl/AvaloniaXamlIlRuntimeCompiler.cs +++ b/src/Markup/Avalonia.Markup.Xaml/XamlIl/AvaloniaXamlIlRuntimeCompiler.cs @@ -23,6 +23,7 @@ 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 AssemblyBuilder _sreAsm; @@ -53,7 +54,8 @@ namespace Avalonia.Markup.Xaml.XamlIl _sreTypeSystem = new SreTypeSystem(); if (_sreBuilder == null) { - _sreCanSave = !AvaloniaLocator.Current.GetService().GetRuntimeInfo().IsCoreClr; + _sreCanSave = AvaloniaLocator.Current.GetService()?.GetRuntimeInfo().IsCoreClr == + false; var name = new AssemblyName(Guid.NewGuid().ToString("N")); if (_sreCanSave) { @@ -77,22 +79,25 @@ namespace Avalonia.Markup.Xaml.XamlIl AssemblyBuilderAccess.RunAndCollect); _sreBuilder = _sreAsm.DefineDynamicModule("XamlIlLoader.ildump"); - } if (_sreMappings == null) _sreMappings = AvaloniaXamlIlLanguage.Configure(_sreTypeSystem); if (_sreXmlns == null) _sreXmlns = XamlIlXmlnsMappings.Resolve(_sreTypeSystem, _sreMappings); + if (_sreContextType == null) + _sreContextType = XamlIlContextDefinition.GenerateContextClass( + _sreTypeSystem.CreateTypeBuilder( + _sreBuilder.DefineType("XamlIlContext")), _sreTypeSystem, _sreMappings); } - static object LoadSre(string xaml, Assembly localAssembly, object rootInstance, Uri uri) + static object LoadSre(string xaml, Assembly localAssembly, object rootInstance, Uri uri, bool isDesignMode) { var success = false; try { - var rv = LoadSreCore(xaml, localAssembly, rootInstance, uri); + var rv = LoadSreCore(xaml, localAssembly, rootInstance, uri, isDesignMode); success = true; return rv; } @@ -104,15 +109,15 @@ namespace Avalonia.Markup.Xaml.XamlIl } - static object LoadSreCore(string xaml, Assembly localAssembly, object rootInstance, Uri uri) + static object LoadSreCore(string xaml, Assembly localAssembly, object rootInstance, Uri uri, bool isDesignMode) { InitializeSre(); var asm = localAssembly == null ? null : _sreTypeSystem.GetAssembly(localAssembly); - var contextType = _sreBuilder.DefineType("XamlIlContext"); + var compiler = new AvaloniaXamlIlCompiler(new XamlIlTransformerConfiguration(_sreTypeSystem, asm, _sreMappings, _sreXmlns, AvaloniaXamlIlLanguage.CustomValueConverter), - _sreTypeSystem.CreateTypeBuilder(contextType)); + _sreContextType); var tb = _sreBuilder.DefineType("Builder_" + Guid.NewGuid().ToString("N") + "_" + uri); IXamlIlType overrideType = null; @@ -121,6 +126,7 @@ namespace Avalonia.Markup.Xaml.XamlIl overrideType = _sreTypeSystem.GetType(rootInstance.GetType()); } + compiler.IsDesignMode = isDesignMode; compiler.ParseAndCompile(xaml, uri?.ToString(), null, _sreTypeSystem.CreateTypeBuilder(tb), overrideType); var created = tb.CreateTypeInfo(); @@ -151,7 +157,8 @@ namespace Avalonia.Markup.Xaml.XamlIl } } - public static object Load(Stream stream, Assembly localAssembly, object rootInstance, Uri uri) + public static object Load(Stream stream, Assembly localAssembly, object rootInstance, Uri uri, + bool isDesignMode) { string xaml; using (var sr = new StreamReader(stream)) @@ -159,7 +166,7 @@ namespace Avalonia.Markup.Xaml.XamlIl #if RUNTIME_XAML_CECIL return LoadCecil(xaml, localAssembly, rootInstance, uri); #else - return LoadSre(xaml, localAssembly, rootInstance, uri); + return LoadSre(xaml, localAssembly, rootInstance, uri, isDesignMode); #endif } diff --git a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlCompiler.cs b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlCompiler.cs index f9139a1beb..8484ae4ec6 100644 --- a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlCompiler.cs +++ b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlCompiler.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers; using XamlIl; using XamlIl.Ast; @@ -11,6 +12,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions public class AvaloniaXamlIlCompiler : XamlIlCompiler { private readonly IXamlIlType _contextType; + private readonly AvaloniaXamlIlDesignPropertiesTransformer _designTransformer; private AvaloniaXamlIlCompiler(XamlIlTransformerConfiguration configuration) : base(configuration, true) { @@ -18,6 +20,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions Transformers.Insert(0, new XNameTransformer()); Transformers.Insert(1, new IgnoredDirectivesTransformer()); + Transformers.Insert(2, _designTransformer = new AvaloniaXamlIlDesignPropertiesTransformer()); // Targeted @@ -55,10 +58,19 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions public const string PopulateName = "__AvaloniaXamlIlPopulate"; public const string BuildName = "__AvaloniaXamlIlBuild"; - + + public bool IsDesignMode + { + get => _designTransformer.IsDesignMode; + set => _designTransformer.IsDesignMode = value; + } + public void ParseAndCompile(string xaml, string baseUri, IFileSource fileSource, IXamlIlTypeBuilder tb, IXamlIlType overrideRootType) { - var parsed = XDocumentXamlIlParser.Parse(xaml); + var parsed = XDocumentXamlIlParser.Parse(xaml, new Dictionary + { + {XamlNamespaces.Blend2008, XamlNamespaces.Blend2008} + }); if (overrideRootType != null) { diff --git a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlDesignPropertiesTransformer.cs b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlDesignPropertiesTransformer.cs new file mode 100644 index 0000000000..c422673d11 --- /dev/null +++ b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlDesignPropertiesTransformer.cs @@ -0,0 +1,63 @@ +using System.Collections.Generic; +using System.Linq; +using XamlIl; +using XamlIl.Ast; +using XamlIl.Transform; + +namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers +{ + public class AvaloniaXamlIlDesignPropertiesTransformer : IXamlIlAstTransformer + { + public bool IsDesignMode { get; set; } + + private static Dictionary DesignDirectives = new Dictionary() + { + ["DataContext"] = "DataContext", + ["DesignWidth"] = "Width", ["DesignHeight"] = "Height", ["PreviewWith"] = "PreviewWith" + }; + + private const string AvaloniaNs = "https://github.com/avaloniaui"; + public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node) + { + if (node is XamlIlAstObjectNode on) + { + for (var c=0; c"; - Assert.Throws(() => AvaloniaXamlLoader.Parse(xaml)); + XamlTestHelpers.AssertThrowsXamlException(() => AvaloniaXamlLoader.Parse(xaml)); } [Fact] @@ -158,7 +162,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml var xaml = @""; - Assert.Throws(() => AvaloniaXamlLoader.Parse(xaml)); + XamlTestHelpers.AssertThrowsXamlException(() => AvaloniaXamlLoader.Parse(xaml)); } [Fact] @@ -587,6 +591,9 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml [Fact] public void Xaml_Binding_Is_Delayed() { + if (!AvaloniaXamlLoader.UseLegacyXamlLoader) + return; + using (UnitTestApplication.Start(TestServices.MockWindowingPlatform)) { var xaml = diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/EventTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/EventTests.cs index 6ea3015138..ddecec0a95 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/EventTests.cs +++ b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/EventTests.cs @@ -31,12 +31,15 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml var loader = new AvaloniaXamlLoader(); var target = new MyButton(); - Assert.Throws(() => loader.Load(xaml, rootInstance: target)); + XamlTestHelpers.AssertThrowsXamlException(() => loader.Load(xaml, rootInstance: target)); } [Fact] public void Exception_Is_Not_Thrown_If_Event_Not_Found_In_Design_Mode() { + // Runtime compiler should properly understand x:Class + if (!AvaloniaXamlLoader.UseLegacyXamlLoader) + return; var xaml = @"