Browse Source

Now passing most of the tests

pull/2322/head
Nikita Tsukanov 7 years ago
parent
commit
d0301bb4c4
  1. 1
      samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj
  2. 4
      src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
  3. 8
      src/Avalonia.DesignerSupport/Remote/RemoteDesignerEntryPoint.cs
  4. 1
      src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
  5. 4
      src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs
  6. 5
      src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/ResourceInclude.cs
  7. 25
      src/Markup/Avalonia.Markup.Xaml/XamlIl/AvaloniaXamlIlRuntimeCompiler.cs
  8. 16
      src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlCompiler.cs
  9. 63
      src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlDesignPropertiesTransformer.cs
  10. 2
      src/Markup/Avalonia.Markup.Xaml/XamlIl/xamlil.github
  11. 13
      tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BasicTests.cs
  12. 5
      tests/Avalonia.Markup.Xaml.UnitTests/Xaml/EventTests.cs
  13. 23
      tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlTestHelpers.cs
  14. 2
      tests/Avalonia.UnitTests/MockAssetLoader.cs

1
samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj

@ -3,6 +3,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
</PropertyGroup>
<ItemGroup>

4
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,

8
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,
}
});
}

1
src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj

@ -56,6 +56,7 @@
<Compile Include="Templates\TreeDataTemplate.cs" />
<Compile Include="XamlIl\AvaloniaXamlIlRuntimeCompiler.cs" />
<Compile Include="XamlIl\CompilerExtensions\Transformers\AvaloniaXamlIlControlTemplateTargetTypeMetadataTransformer.cs" />
<Compile Include="XamlIl\CompilerExtensions\Transformers\AvaloniaXamlIlDesignPropertiesTransformer.cs" />
<Compile Include="XamlIl\CompilerExtensions\Transformers\AvaloniaXamlIlMetadataRemover.cs" />
<Compile Include="XamlIl\CompilerExtensions\XamlIlAvaloniaPropertyHelper.cs" />
<Compile Include="XamlIl\CompilerExtensions\AvaloniaXamlIlCompiler.cs" />

4
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;
/// <summary>
/// Initializes a new instance of the <see cref="AvaloniaXamlLoader"/> 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()

5
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/ResourceInclude.cs

@ -54,6 +54,11 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
/// <inhertidoc/>
public override object ProvideValue(IServiceProvider serviceProvider)
{
return ProvideTypedValue(serviceProvider);
}
public ResourceInclude ProvideTypedValue(IServiceProvider serviceProvider)
{
var tdc = (ITypeDescriptorContext)serviceProvider;
_baseUri = tdc?.GetContextBaseUri();

25
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<IRuntimePlatform>().GetRuntimeInfo().IsCoreClr;
_sreCanSave = AvaloniaLocator.Current.GetService<IRuntimePlatform>()?.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
}

16
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<string, string>
{
{XamlNamespaces.Blend2008, XamlNamespaces.Blend2008}
});
if (overrideRootType != null)
{

63
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<string, string> DesignDirectives = new Dictionary<string, string>()
{
["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<on.Children.Count;)
{
var ch = on.Children[c];
if (ch is XamlIlAstXmlDirective directive
&& directive.Namespace == XamlNamespaces.Blend2008
&& DesignDirectives.TryGetValue(directive.Name, out var mapTo))
{
if (!IsDesignMode)
// Just remove it from AST in non-design mode
on.Children.RemoveAt(c);
else
{
// Map to an actual property in `Design` class
on.Children[c] = new XamlIlAstXamlPropertyValueNode(ch,
new XamlIlAstNamePropertyReference(ch,
new XamlIlAstXmlTypeReference(ch, AvaloniaNs, "Design"),
mapTo, on.Type), directive.Values);
c++;
}
}
// Remove all "Design" attached properties in non-design mode
else if (
!IsDesignMode
&& ch is XamlIlAstXamlPropertyValueNode pv
&& pv.Property is XamlIlAstNamePropertyReference pref
&& pref.DeclaringType is XamlIlAstXmlTypeReference dref
&& dref.XmlNamespace == AvaloniaNs && dref.Name == "Design"
)
{
on.Children.RemoveAt(c);
}
else
c++;
}
}
return node;
}
}
}

2
src/Markup/Avalonia.Markup.Xaml/XamlIl/xamlil.github

@ -1 +1 @@
Subproject commit c8b95cfa9da04dbf4afdd903c9aa76efefd59e42
Subproject commit b318b6dcc67370f7ebea1e3c6741a0b6d4dd5db1

13
tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BasicTests.cs

@ -1,6 +1,7 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using Avalonia.Collections;
using Avalonia.Controls;
using Avalonia.Controls.Presenters;
@ -17,6 +18,7 @@ using Portable.Xaml;
using System.Collections;
using System.ComponentModel;
using System.Linq;
using System.Xml;
using Xunit;
namespace Avalonia.Markup.Xaml.UnitTests.Xaml
@ -61,6 +63,8 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml
[Fact]
public void AvaloniaProperty_With_Getter_And_No_Setter_Is_Set()
{
if(!AvaloniaXamlLoader.UseLegacyXamlLoader)
return;
var xaml =
@"<local:NonControl xmlns='https://github.com/avaloniaui'
xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'
@ -142,14 +146,14 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml
Assert.Equal("Foo", ToolTip.GetTip(target));
}
[Fact]
public void NonExistent_Property_Throws()
{
var xaml =
@"<ContentControl xmlns='https://github.com/avaloniaui' DoesntExist='foo'/>";
Assert.Throws<XamlObjectWriterException>(() => AvaloniaXamlLoader.Parse<ContentControl>(xaml));
XamlTestHelpers.AssertThrowsXamlException(() => AvaloniaXamlLoader.Parse<ContentControl>(xaml));
}
[Fact]
@ -158,7 +162,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml
var xaml =
@"<ContentControl xmlns='https://github.com/avaloniaui' TextBlock.Text='foo'/>";
Assert.Throws<XamlObjectWriterException>(() => AvaloniaXamlLoader.Parse<ContentControl>(xaml));
XamlTestHelpers.AssertThrowsXamlException(() => AvaloniaXamlLoader.Parse<ContentControl>(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 =

5
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<XamlObjectWriterException>(() => 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 = @"<Button xmlns='https://github.com/avaloniaui' Click='NotFound'/>";
var loader = new AvaloniaXamlLoader { IsDesignMode = true };
var target = new MyButton();

23
tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlTestHelpers.cs

@ -0,0 +1,23 @@
using System;
using System.Xml;
using Portable.Xaml;
namespace Avalonia.Markup.Xaml.UnitTests.Xaml
{
public class XamlTestHelpers
{
public static void AssertThrowsXamlException(Action cb)
{
try
{
cb();
}
catch (Exception e)
{
if(e is XamlObjectWriterException || e is XmlException)
return;
}
throw new Exception("Expected to throw xaml exception");
}
}
}

2
tests/Avalonia.UnitTests/MockAssetLoader.cs

@ -34,7 +34,7 @@ namespace Avalonia.UnitTests
public Assembly GetAssembly(Uri uri, Uri baseUri = null)
{
throw new NotImplementedException();
return null;
}
public IEnumerable<Uri> GetAssets(Uri uri, Uri baseUri)

Loading…
Cancel
Save