Giter Site home page Giter Site logo

xamlx's Introduction

XamlX

General purpose pluggable XAML compiler with no runtime dependencies. Currently being used by Avalonia project as the XAML engine.

The compiler isn't tied to Avalonia in any way, shape or form and can be used for any purposes by configuring XamlLanguageTypeMappings to match the needs of your particular framework. Further customization can be done by AST manipulations, see examples of those in Avalonia repository.

default

Implemented features

  • Direct convertion of XML to objects (instantiation, setting properties, setting attached properties)
  • Create / Populate semantics
  • Properties with [DeferredContent] get assigned a Func<IServiceProvider, object> delegate which emits child nodes (can be customized, see DeferredContentTests)
  • Implicit type converting for types with static T Parse(string, [IFormatProvider]) method (e. g. int, double, TimeSpan, etc)
  • Compile-time parsing of primitive types (numbers and boolean)
  • Support for TypeConverterAttribute and a way to provide conveters for types without one.
  • Support for [Content] attribute both for direct content and for collections
  • Support for collections themselves (e. g. <List x:TypeArguments="sys:String"></List>)
  • x:Arguments Directive
  • x:TypeArguments Directive
  • x:Key Directive
  • Markup extensions with extension point for handling non-convertable values at runtime (e. g. Binding)
  • Duck-typing for markup extensions, following signatures are checked for markup extension detection (T is anything that's not System.Object):
T ProvideValue();
T ProvideValue(IServiceProvider provider);
object ProvideValue();
object ProvideValue(IServiceProvider provider);

If strongly typed markup extension overload is available, it's used to avoid unnecessary casts and boxing

  • x:Null Markup Extension (intrinsic: ldnull)

  • x:Type Markup Extension (intrinsic: ldtoken + Type.FromRuntimeHandle)

  • x:Static Markup Extension (intrinsic: properties (call get_PropName), fields (ldsfld), constants/enums (ldc_*/ldstr)

  • IRootObjectProvider

  • UsableDuringInitializationAttribute (assign first, set properties/contents later)

  • ISupportInitialize

  • XAML parents stack (see IXamlParentsStack in tests) as an lightweight alternative for IAmbientProvider

  • Support for mc:Ignorable

  • IProvideValueTarget (property name is provided for regular properties, RuntimeMethodInfo is provided for attached ones)

  • IUriContext

  • Primitive types (sys:String, sys:Int32, sys:TimeSpan etc) https://docs.microsoft.com/en-us/dotnet/framework/xaml-services/built-in-types-for-common-xaml-language-primitives

  • Runtime xmlns information via IXamlXmlNamespaceInfoProvider (provides Dictionary<string, List<(string clrNamespace, string asm)>)

  • xml:space Handling in XAML (automatically via XmlReader)

  • Event handlers from codebehind

Architecture

The flow looks like this:

  1. Parse XAML into some basic AST (we can use different language markup parser at this point, like C#/VB in Roslyn)
  2. Transform AST via visitors. At this stage types get resolved, property values get transformed either in setting properties or collection access, etc
  3. Emit IL code

Features to implement (TODO)

Features marked with [dontneed] aren't required for the Avalonia project, but might be implemented later if the need arises. Features marked with [opt] are considered optional and will be implemented after non-optional features

  • x:Array Markup Extension [opt]
  • x:Name Directive [opt]
  • x:FactoryMethod Directive [opt]
  • x:Reference Markup Extension [opt]
  • xml:lang Handling in XAML [dontneed]
  • IDestinationTypeProvider (probably don't need it) [dontneed]

These are questinable due to heavy reliance on reflection:

  • IXamlTypeResolver (can be implemented in runtime via IXamlXmlNamespaceInfoProviderV1) [dontneed]
  • IXamlNameResolver (probably without forward references) [dontneed]
  • IXamlNamespaceResolver [dontneed]

These are framework-specific and can be implemented via custom transformers/emitters or custom IServiceProvider

  • x:Property Directive
  • x:Uid Directive
  • x:XData Intrinsic XAML Type
  • x:Shared Attribute
  • x:Class Directive
  • x:Subclass Directive
  • x:ClassModifier Directive
  • x:FieldModifier Directive
  • x:Member Directive
  • x:Members Directive

Won't fix:

  • IXamlSchemaContextProvider: we don't have a schema context at run time
  • IAmbientProvider - we don't have "xaml type system" at run time, only plain CLR types

Future: x:Code Intrinsic XAML Type (probably use Roslyn to inline C# code)

Possible optimizations (TODO):

  • Right now if IXamlParentStack feature is enabled, each object initialization triggers push/pop to the parent objects stack. That could be optimized out for objects that don't have anything that uses IServiceProvider (markup extensions, TypeConverter's, DeferredContent) inside of them
  • Parent's RootObject could be saved in a closure, right deferred content builder attempts to extract it from passed IServiceProvider

xamlx's People

Contributors

bclehmann avatar billhenn avatar busitech avatar donandren avatar fornever avatar gillibald avatar grokys avatar jkoritzinsky avatar jmacato avatar jp2masa avatar kekekeks avatar marchingcube avatar maxkatz6 avatar mgnslndh avatar mrjul avatar shadowdancer avatar shartte avatar takoooooo avatar workgroupengineering avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

xamlx's Issues

XamlParserTests crashes with dotnet test exception for net47

Hello!

XamlParserTests crashes with dotnet test exception for net47

dotnet test -f net47 --filter Compiler_Should_Compile_Simple_Xaml .\tests\XamlParserTests\XamlParserTests.csproj
Test run for D:\a\XamlX\XamlX\tests\XamlParserTests\bin\Debug\net47\XamlParserTests.dll(.NETFramework,Version=v4.7)
Microsoft (R) Test Execution Command Line Tool Version 16.7.0
Copyright (c) Microsoft Corporation.  All rights reserved.

Starting test execution, please wait...

A total of 1 test files matched the specified pattern.
[xUnit.net 00:00:00.19] xUnit.net VSTest Adapter v2.4.3+1b45f5407b (32-bit Desktop .NET 4.0.30319.42000)
[xUnit.net 00:00:03.15]   Discovering: XamlParserTests
[xUnit.net 00:00:03.42]   Discovered:  XamlParserTests
[xUnit.net 00:00:03.43]   Starting:    XamlParserTests
  √ XamlParserTests.BasicCompilerTests.Compiler_Should_Compile_Simple_Xaml(populate: False) [1s 141ms]
[xUnit.net 00:00:05.66]     XamlParserTests.BasicCompilerTests.Compiler_Should_Compile_Simple_Xaml(populate: True) [FAIL]
[xUnit.net 00:00:05.66]       System.InvalidOperationException : Collection was modified; enumeration operation may not execute.
[xUnit.net 00:00:05.66]       Stack Trace:
[xUnit.net 00:00:05.67]            at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
[xUnit.net 00:00:05.67]            at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
[xUnit.net 00:00:05.67]            at System.Collections.Generic.List`1.Enumerator.MoveNext()
[xUnit.net 00:00:05.67]         D:\a\XamlX\XamlX\src\XamlX\Transform\XamlXmlnsMappings.cs(22,0): at XamlX.Transform.XamlXmlnsMappings.Resolve(IXamlTypeSystem typeSystem, XamlLanguageTypeMappings typeMappings)
[xUnit.net 00:00:05.67]         D:\a\XamlX\XamlX\src\XamlX\Transform\TransformerConfiguration.cs(59,0): at XamlX.Transform.TransformerConfiguration..ctor(IXamlTypeSystem typeSystem, IXamlAssembly defaultAssembly, XamlLanguageTypeMappings typeMappings, XamlXmlnsMappings xmlnsMappings, XamlValueConverter customValueConverter)
[xUnit.net 00:00:05.67]         CompilerTestBase.cs(30,0): at XamlParserTests.CompilerTestBase..ctor(IXamlTypeSystem typeSystem)
[xUnit.net 00:00:05.67]         CompilerTestBase.cs(82,0): at XamlParserTests.CompilerTestBase..ctor()
[xUnit.net 00:00:05.67]            at XamlParserTests.BasicCompilerTests..ctor()
[xUnit.net 00:00:05.67]            at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
[xUnit.net 00:00:05.67]   Finished:    XamlParserTests
  X XamlParserTests.BasicCompilerTests.Compiler_Should_Compile_Simple_Xaml(populate: True) [1ms]
  Error Message:
   System.InvalidOperationException : Collection was modified; enumeration operation may not execute.
  Stack Trace:
     at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
   at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
   at System.Collections.Generic.List`1.Enumerator.MoveNext()
   at XamlX.Transform.XamlXmlnsMappings.Resolve(IXamlTypeSystem typeSystem, XamlLanguageTypeMappings typeMappings) in D:\a\XamlX\XamlX\src\XamlX\Transform\XamlXmlnsMappings.cs:line 22
   at XamlX.Transform.TransformerConfiguration..ctor(IXamlTypeSystem typeSystem, IXamlAssembly defaultAssembly, XamlLanguageTypeMappings typeMappings, XamlXmlnsMappings xmlnsMappings, XamlValueConverter customValueConverter) in D:\a\XamlX\XamlX\src\XamlX\Transform\TransformerConfiguration.cs:line 59
   at XamlParserTests.CompilerTestBase..ctor(IXamlTypeSystem typeSystem) in D:\a\XamlX\XamlX\tests\XamlParserTests\CompilerTestBase.cs:line 30
Test Run Failed.
   at XamlParserTests.CompilerTestBase..ctor() in D:\a\XamlX\XamlX\tests\XamlParserTests\CompilerTestBase.cs:line 82
   at XamlParserTests.BasicCompilerTests..ctor()
   at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)

Total tests: 2
     Passed: 1
     Failed: 1
 Total time: 11.4751 Seconds

If you write ToList() here, then everything will be fine

public IReadOnlyList<IXamlAssembly> Assemblies => _assemblies;

Unlike #33, here it seems to me that the problem of the main library

Emit DynamicDependency for CompiledAvaloniaXaml types to prevent compiled xaml from trimming

Emit DynamicDependency for CompiledAvaloniaXaml.* on program entry point to prevent from trimming when compile against net5.0+.

For example,

[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(CompiledAvaloniaXaml.!AvaloniaResources))]
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(CompiledAvaloniaXaml.!EmbeddedResource))]
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(CompiledAvaloniaXaml.!IndexerAccessorFactoryClosure))]
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(CompiledAvaloniaXaml.!XamlLoader))]
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(CompiledAvaloniaXaml.XamlIlContext))]
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(CompiledAvaloniaXaml.XamlIlHelpers))]
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(CompiledAvaloniaXaml.XamlIlTrampolines))]
static void Main() // or other method which is directly referenced in code path
{
    // ...
}

This can ensure compiled avalonia xaml types and members won't be trimmed by ILLinker even with /p:TrimmerDefaultAction=true.

Loading xaml on demand to decrease app size after trimming

Currently XamlX emitted a huge !CompiledAvaloniaXaml.!XamlLoader.TryLoad which puts all xaml files into a single method, which leads to all generated code being preserved after trimming, even if some of those xaml files were not being used.

For example, the !XamlLoader.TryLoad for Avalonia.Themes.Fluent is:

	public static object TryLoad(string P_0)
	{
		if (string.Equals(P_0, "avares://Avalonia.Themes.Fluent/Accents/AccentColors.xaml"))
		{
			return CompiledAvaloniaXaml.!AvaloniaResources.Build:/Accents/AccentColors.xaml(XamlIlRuntimeHelpers.CreateRootServiceProviderV2());
		}
		if (string.Equals(P_0, "avares://Avalonia.Themes.Fluent/Accents/Base.xaml"))
		{
			return CompiledAvaloniaXaml.!AvaloniaResources.Build:/Accents/Base.xaml(XamlIlRuntimeHelpers.CreateRootServiceProviderV2());
		}
		if (string.Equals(P_0, "avares://Avalonia.Themes.Fluent/Accents/BaseDark.xaml"))
		{
			return CompiledAvaloniaXaml.!AvaloniaResources.Build:/Accents/BaseDark.xaml(XamlIlRuntimeHelpers.CreateRootServiceProviderV2());
		}
		if (string.Equals(P_0, "avares://Avalonia.Themes.Fluent/Accents/BaseLight.xaml"))
		{
			return CompiledAvaloniaXaml.!AvaloniaResources.Build:/Accents/BaseLight.xaml(XamlIlRuntimeHelpers.CreateRootServiceProviderV2());
		}
		if (string.Equals(P_0, "avares://Avalonia.Themes.Fluent/Accents/FluentControlResourcesDark.xaml"))
		{
			return CompiledAvaloniaXaml.!AvaloniaResources.Build:/Accents/FluentControlResourcesDark.xaml(XamlIlRuntimeHelpers.CreateRootServiceProviderV2());
		}
		if (string.Equals(P_0, "avares://Avalonia.Themes.Fluent/Accents/FluentControlResourcesLight.xaml"))
		{
			return CompiledAvaloniaXaml.!AvaloniaResources.Build:/Accents/FluentControlResourcesLight.xaml(XamlIlRuntimeHelpers.CreateRootServiceProviderV2());
		}
		if (string.Equals(P_0, "avares://Avalonia.Themes.Fluent/Controls/AutoCompleteBox.xaml"))
		{
			return CompiledAvaloniaXaml.!AvaloniaResources.Build:/Controls/AutoCompleteBox.xaml(XamlIlRuntimeHelpers.CreateRootServiceProviderV2());
		}
		if (string.Equals(P_0, "avares://Avalonia.Themes.Fluent/Controls/Button.xaml"))
		{
			return CompiledAvaloniaXaml.!AvaloniaResources.Build:/Controls/Button.xaml(XamlIlRuntimeHelpers.CreateRootServiceProviderV2());
		}
		if (string.Equals(P_0, "avares://Avalonia.Themes.Fluent/Controls/ButtonSpinner.xaml"))
		{
			return CompiledAvaloniaXaml.!AvaloniaResources.Build:/Controls/ButtonSpinner.xaml(XamlIlRuntimeHelpers.CreateRootServiceProviderV2());
		}
		if (string.Equals(P_0, "avares://Avalonia.Themes.Fluent/Controls/Calendar.xaml"))
		{
			return CompiledAvaloniaXaml.!AvaloniaResources.Build:/Controls/Calendar.xaml(XamlIlRuntimeHelpers.CreateRootServiceProviderV2());
		}
		if (string.Equals(P_0, "avares://Avalonia.Themes.Fluent/Controls/CalendarButton.xaml"))
		{
			return CompiledAvaloniaXaml.!AvaloniaResources.Build:/Controls/CalendarButton.xaml(XamlIlRuntimeHelpers.CreateRootServiceProviderV2());
		}
		if (string.Equals(P_0, "avares://Avalonia.Themes.Fluent/Controls/CalendarDatePicker.xaml"))
		{
			return CompiledAvaloniaXaml.!AvaloniaResources.Build:/Controls/CalendarDatePicker.xaml(XamlIlRuntimeHelpers.CreateRootServiceProviderV2());
		}
		if (string.Equals(P_0, "avares://Avalonia.Themes.Fluent/Controls/CalendarDayButton.xaml"))
		{
			return CompiledAvaloniaXaml.!AvaloniaResources.Build:/Controls/CalendarDayButton.xaml(XamlIlRuntimeHelpers.CreateRootServiceProviderV2());
		}
                // .....
		return null;
	}

which leads to all those compiled xaml code being kept even if the user only use a Button in the app.

To make the loading process on demand, instead of emitting all things in a single TryLoad, emitting TryLoad_{uri} is a more properate choise. In this case, the TryLoad for avares://Avalonia.Themes.Fluent/Accents/AccentColors.xaml will become:

public static object TryLoad_avares://Avalonia.Themes.Fluent/Accents/AccentColors.xaml
{
    return CompiledAvaloniaXaml.!AvaloniaResources.Build:/Accents/AccentColors.xaml(XamlIlRuntimeHelpers.CreateRootServiceProviderV2());
}

To achieve trimming compatibility, we also need to introduce an attribute which save related types using string or Type with DynamicallyAccessedMembers, so that the trimmer can figure out which types are being used during compilation.

This is a breaking change, I would like to see the change landing before 11.0 GA getting released.

x:Static with "Path"

Hi, not sure if this is intended or a limitation of not being able to give a path to an x:Static statement?

Here an example what I try to use:

<DataTriggerBehavior Binding="{Binding Action}"
                     ComparisonCondition="Equal"
                     Value="{x:Static local:ProfileActionPageViewModel.ProfileAction.Delete}">
    <ChangePropertyAction TargetObject="{Binding $parent[TextBlock]}"
                          PropertyName="Text"
                          Value="Deleting a profile..." />
</DataTriggerBehavior>

Since local:ProfileActionPageViewModel.ProfileAction.Delete does not work, I only got it working when I moved the enum definition out of the class scope into the namespace scope and reference it like so local:ProfileAction.Delete.

Is this a limitation of x:Static or is this a bug (not yet implemented feature)?
Or am I doing anything wrong?

PS: produced error:
ProfileActionPage.xaml(46,93,46,93): Avalonia error XAMLIL: Unable to resolve ProfileAction.Create as static field, property, constant or enum value Zeile 46, Position 93.

xamlx error

similar to ForNeVeR/AvaloniaRider#95

XamlParseException at 8:9: Unable to resolve type DesignInstance from namespace http://schemas.microsoft.com/expression/blend/2008 Line 8, position 9. XamlX.XamlParseException: Unable to resolve type DesignInstance from namespace http://schemas.microsoft.com/expression/blend/2008 Line 8, position 9. at XamlX.Transform.Transformers.TypeReferenceResolver.ResolveTypeCore(AstTransformationContext context, String xmlns, String name, Boolean isMarkupExtension, List1 typeArguments, IXamlLineInfo lineInfo, Boolean strict) at XamlX.Transform.Transformers.TypeReferenceResolver.ResolveType(AstTransformationContext context, String xmlns, String name, Boolean isMarkupExtension, List1 typeArguments, IXamlLineInfo lineInfo, Boolean strict) at XamlX.Transform.Transformers.TypeReferenceResolver.ResolveType(AstTransformationContext context, XamlAstXmlTypeReference xmlref, Boolean strict) at XamlX.Transform.Transformers.TypeReferenceResolver.Transform(AstTransformationContext context, IXamlAstNode node) at XamlX.Transform.AstTransformationContext.Visitor.Visit(IXamlAstNode node) at XamlX.Ast.XamlAstNode.Visit(IXamlAstVisitor visitor) at XamlX.Ast.XamlAstObjectNode.VisitChildren(IXamlAstVisitor visitor) at XamlX.Ast.XamlAstNode.Visit(IXamlAstVisitor visitor) at XamlX.Ast.XamlAstNode.VisitList[T](IList1 list, IXamlAstVisitor visitor) at XamlX.Ast.XamlAstXamlPropertyValueNode.VisitChildren(IXamlAstVisitor visitor) at XamlX.Ast.XamlAstNode.Visit(IXamlAstVisitor visitor) at XamlX.Ast.XamlAstNode.VisitList[T](IList1 list, IXamlAstVisitor visitor) at XamlX.Ast.XamlAstObjectNode.VisitChildren(IXamlAstVisitor visitor) at XamlX.Ast.XamlAstNode.Visit(IXamlAstVisitor visitor) at XamlX.Compiler.XamlCompiler2.Transform(XamlDocument doc, Boolean strict) at Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.AvaloniaXamlIlCompiler.ParseAndCompile(String xaml, String baseUri, IFileSource fileSource, IXamlTypeBuilder1 tb, IXamlType overrideRootType) at Avalonia.Markup.Xaml.XamlIl.AvaloniaXamlIlRuntimeCompiler.LoadSreCore(String xaml, Assembly localAssembly, Object rootInstance, Uri uri, Boolean isDesignMode) at Avalonia.Markup.Xaml.XamlIl.AvaloniaXamlIlRuntimeCompiler.LoadSre(String xaml, Assembly localAssembly, Object rootInstance, Uri uri, Boolean isDesignMode) at Avalonia.Markup.Xaml.XamlIl.AvaloniaXamlIlRuntimeCompiler.Load(Stream stream, Assembly localAssembly, Object rootInstance, Uri uri, Boolean isDesignMode) at Avalonia.Designer.HostApp.DesignXamlLoader.Load(Stream stream, Assembly localAsm, Object o, Uri baseUri, Boolean designMode) at Avalonia.DesignerSupport.DesignWindowLoader.LoadDesignerWindow(String xaml, String assemblyPath, String xamlFileProjectPath) at Avalonia.DesignerSupport.Remote.RemoteDesignerEntryPoint.<>c__DisplayClass17_0.b__0()

Add support for x:Reference markup extension

I have use case for x:Reference markup extension when used in Avalonia for defining docking layouts using xaml.

Example:

<Dock xmlns="https://github.com/avaloniaui" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:vm="clr-namespace:Demo.ViewModels;assembly=Demo"
      ActiveLayout="{x:Reference layout1}">
  <Dock.Items>
      <vm:Item1ViewModel x:Name="item1"/>
      <vm:Item2ViewModel x:Name="item2"/>
      <vm:Item3ViewModel x:Name="item3"/>
  <Dock.Items>
  <Dock.Layouts>
    <Layout x:Name="layout1">
      <x:Reference Name="item1"/>
      <x:Reference Name="item2"/>
    </Layout>
    <Layout x:Name="layout2">
      <x:Reference Name="item1"/>
      <x:Reference Name="item2"/>
      <x:Reference Name="item3"/>
    </Layout>
  </Dock.Layouts>
</Dock>

In my example I have two separate instances of Layout object (layout1 and layout2) but both reference same child items. This allows switching layouts during runtime (by setting ActiveLayout property) while items retain their state.

Dock:

https://github.com/wieslawsoltes/Dock/blob/94c8a59596c0e01139285b071b37d0679066f88f/samples/AvaloniaDemo.Perspectives/Layouts/Default.xaml#L23-L54

https://github.com/wieslawsoltes/Dock/blob/94c8a59596c0e01139285b071b37d0679066f88f/src/Dock.Model.Avalonia/Core/DockableBase.cs#L12

Docs:

https://docs.microsoft.com/en-us/dotnet/framework/xaml-services/x-reference-markup-extension

ProvideValueTarget returns incorrect(?) TargetObject when nested markup extension is used on property

As in title. I'm not sure whether it's best to return current result or the owner of the property or null like WPF does[1]. Here is a test demonstrating the situation:
https://gist.github.com/miloszkukla/871d2321cc9d038dac936a6030add689

[1] https://docs.microsoft.com/en-us/dotnet/api/system.windows.markup.iprovidevaluetarget?view=netframework-4.8

An example case where the values from IProvideValueTarget are null even if the service is available is if your markup extension is nested within another markup extension, such as a Binding. An implementation that relies on IProvideValueTarget should always check for null values if only for the purpose of throwing a specific exception, if that is your intended design.

[Question] Serializze AST

Do you have any examples of how to sterilize the AST? I tried with System.Text.Json but I get empty files.

Winfx schema version 2009 is failing

During the migration from Xamarin to Avalonia I experienced this issue:
When I keep using the 2009 reference (as it was working fine in the Xamarin project) xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" it throws CSC : error AXN0002: XamlX.XamlParseException: Unable to resolve type Static from namespace http://schemas.microsoft.com/winfx/2009/xaml
When "downgrading" to xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" it works.
The failing statement that produces the error is this: Text="{x:Static common:Statics.ApplicationTitle}"

BTW: Every time a XamlX error comes up it tells me the line and position but it does not tell me which file is failing. Shall I file an extra issue for this or is there a solution that the file is also printed with the error message?

unable to resolve type system.uri error

I try to run BasicCompilerTests in my .net 5.0 project:

                XamlParserTests.BasicCompilerTests test = new XamlParserTests.BasicCompilerTests();
                test.Compiler_Should_Compile_Simple_Xaml(false);

Got the unable to resolve type system.uri error.

Unable to resolve content property on Panel property...

I wanted to simply add a Getter only property to VisualLayerManager

It was called ChromeOverlayLayer and of type Panel... only a getter was declared and the value set in the getter if it didnt exist already.

I expected: <VisualLayerManager.ChromeOverlayLayer> <TitleBar /> to just add a titlebar to it..
it actually complains it cant find a setter to set ChromeOverlayLayer property to titlebar.

Tests/benchmarks failing

This is mentioned in #30 but that has been closed: the test and benchmarks suite currently does not run. I can see the following problems in a freshly cloned repro:

  • Benchmarks fails to compile:
5>Precompiling D:\projects\grokys\XamlX\src\Benchmarks\bin\Debug\netcoreapp2.2\Benchmarks.dll
5>D:\projects\grokys\XamlX\src\Benchmarks\Benchmarks.csproj(24,9): error : Could not execute because the specified command or file was not found.
5>D:\projects\grokys\XamlX\src\Benchmarks\Benchmarks.csproj(24,9): error : Possible reasons for this include:
5>D:\projects\grokys\XamlX\src\Benchmarks\Benchmarks.csproj(24,9): error :   * You misspelled a built-in dotnet command.
5>D:\projects\grokys\XamlX\src\Benchmarks\Benchmarks.csproj(24,9): error :   * You intended to execute a .NET program, but dotnet-D:\projects\grokys\XamlX\src\Benchmarks\\..\BenchmarksCompiler\bin\Debug\netcoreapp2.2\BenchmarksCompiler.dll does not exist.
5>D:\projects\grokys\XamlX\src\Benchmarks\Benchmarks.csproj(24,9): error :   * You intended to run a global tool, but a dotnet-prefixed executable with this name could not be found on the PATH.
5>D:\projects\grokys\XamlX\src\Benchmarks\Benchmarks.csproj(24,9): error MSB3073: The command "dotnet   "D:\projects\grokys\XamlX\src\Benchmarks\\..\BenchmarksCompiler\bin\Debug\netcoreapp2.2\BenchmarksCompiler.dll" "D:\projects\grokys\XamlX\src\Benchmarks\/obj\Debug\netcoreapp2.2\Benchmarks.dll"" exited with code 1.
  • File.WriteAllBytes("testasm.dll", data) throws (#30)
Message: 
    System.IO.IOException : The process cannot access the file '.\XamlX\tests\CecilNetstandardTests\bin\Debug\netcoreapp3.1\testasm.dll' because it is being used by another process.
  Stack Trace: 
    FileStream.ValidateFileHandle(SafeFileHandle fileHandle)
    FileStream.CreateFileOpenHandle(FileMode mode, FileShare share, FileOptions options)
    FileStream.ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options)
    FileStream.ctor(String path, FileMode mode, FileAccess access, FileShare share)
    File.InternalWriteAllBytes(String path, Byte[] bytes)
    File.WriteAllBytes(String path, Byte[] bytes)
    CompilerTestBase.Compile(String xaml) line 75
    BasicCompilerTests.Compiler_Should_Compile_Simple_Xaml(Boolean populate) line 27
  • CompilerTestBase.GetCallbacks fails on net47:
Message: 
    System.IO.FileNotFoundException : Could not load file or assembly 'CecilNetstandardTests, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
  Stack Trace: 
    Signature.GetSignature(Void* pCorSig, Int32 cCorSig, RuntimeFieldHandleInternal fieldHandle, IRuntimeMethodInfo methodHandle, RuntimeType declaringType)
    RuntimeMethodInfo.FetchNonReturnParameters()
    RuntimeMethodInfo.GetParameters()
    TypeExtensions.GetParametersCached(MethodBase method)
    Expression.ValidateMethodAndGetParameters(Expression instance, MethodInfo method)
    Expression.Call(MethodInfo method, Expression arg0)
    CompilerTestBase.GetCallbacks(Type created) line 124
    CompilerTestBase.Compile(String xaml) line 65
    BasicCompilerTests.Compiler_Should_Compile_Simple_Xaml(Boolean populate) line 27
  • CecilTests/CecilNetstandardTests are being built for netstandard2.0 which is not a valid TFM for unit tests due to it being an API not a platform causing the tests to show up in the VS test explorer but not be runnable

Support for overriding Content attribute in derived classes

Hi, thank you for this library.
Consider the following situation:

    class Base
    {
        [Content]
        public Base[] BaseProp { get; }
    }

    class Derived : Base
    {
        [Content]
        public Base[] DerivedProp { get; }
    }

With this code I would like to override the "content" property in Derived class to use DerivedProp instead of BaseProp.
Then when parsing the following XAML:

    <Derived>
        <Base />
        <Base />
    </Derived>

I get error: XamlX.XamlTypeSystemException: 'Content (or substitute) attribute is declared on multiple properties of Derived'

Commenting the following code here:

                if (GetCustomAttribute(p, TypeMappings.ContentAttributes).Any())
                {
                    //if (found != null && !p.Equals(found))
                    //    throw new XamlTypeSystemException(
                    //        "Content (or substitute) attribute is declared on multiple properties of " + type.GetFqn());
                    found = p;
                }

seems to solve this problem for me.

Maybe there is a different better way to achieve this? If not, should we cover this case in the library? I can submit a PR if needed.

Unable to parse binding expression

IsVisible="{Binding !$parent[cont|MetroWindow].DataContext.LockScreen.IsLocked}"

gives a runtime error.

but:

IsVisible="{Binding !$parent[Window].DataContext.LockScreen.IsLocked}"

works

Cannot compile the project after deleting xaml and code behind files that were compiled before

I've been seeing compile errors like this show up from time to time after deleting files/switching branches

Unable to find type ControlCatalog.Pages.AcrylicPage Line 1, position 2. [C:\Repositories\Avalonia\samples\ControlCatalog\ControlCatalog.csproj]
AvaloniaBuildTasks.targets(94, 5): [MSB3073] The command "dotnet msbuild /nodereuse:false ControlCatalog.csproj /t:CompileAvaloniaXaml /p:_AvaloniaForceInternalMSBuild=true /p:Configuration=Debug /p:TargetFramework=netstandard2.0 /p:BuildProjectReferences=false" exited with code 1.

MSBuild log shows that resource generation task was skipped but xaml compilation was triggered again and is now complaining about having xaml without matching types.

Build started 10/28/2020 10:41:36 PM.
Logging verbosity is set to: Normal. 1>Project "C:\Repositories\Avalonia\samples\ControlCatalog\ControlCatalog.csproj" on node 1 (build target(s)).
1>GenerateAvaloniaResources:
Skipping target "GenerateAvaloniaResources" because all output files are up-to-date with respect to the input files.
GenerateTargetFrameworkMonikerAttribute:
Skipping target "GenerateTargetFrameworkMonikerAttribute" because all output files are up-to-date with respect to the input files.

I can easily repro this by:

  1. Open Avalonia ControlCatalog project
  2. Remove AcrylicPage from MainView (https://github.com/AvaloniaUI/Avalonia/blob/master/samples/ControlCatalog/MainView.xaml#L14)
  3. Compile
  4. Delete AcrylicPage.xaml and AcrylicPage.xaml.cs (I've used explorer)
  5. Compile - it fails here

To make this compile again one has to change something in the project which generates correct resources.

`ExpressionParseError` when using `{TemplateBinding .}`

As the title suggests, using a TemplateBinding with a path to the binding object itself ({TemplateBinding .}) causes an exception during compile time. I am forced to use the verbose syntax of {Binding ., RelativeSource={RelativeSource TemplatedParent}}.

FirmwareItem.axaml(83, 29): [XAMLIL] Internal compiler error while transforming node XamlX.Ast.XamlAstObjectNode:
Avalonia.Data.Core.ExpressionParseException: Unexpected '.'.
   at Avalonia.Markup.Xaml.Parsers.PropertyParser.Parse(CharacterReader r)
   at Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.XamlIlAvaloniaPropertyHelper.CreateNode(AstTransformationContext context, String propertyName, IXamlAstTypeReference selectorTypeReference, IXamlLineInfo lineInfo)
   at Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.AvaloniaXamlIlLanguage.CustomValueConverter(AstTransformationContext context, IXamlAstValueNode node, IXamlType type, IXamlAstValueNode& result)
   at XamlX.Transform.XamlTransformHelpers.TryConvertValue(AstTransformationContext context, IXamlAstValueNode node, IXamlType type, XamlAstClrProperty propertyContext, IXamlAstValueNode& rv)
   at XamlX.Transform.Transformers.ConstructableObjectTransformer.TransformArgumentsAndGetConstructor(AstTransformationContext context, XamlAstObjectNode n)
   at XamlX.Transform.Transformers.Con... Line 83, position 29.

ArgumentOutOfRange exception in ResolveContentPropertyTransformer.Transform

There'e multiple scenarios when compilling axaml throws internal compiller error (ArgumentOutOfRangeException). This exception occures when you have in source axaml file any xml elements of types which has no Content property and has no any Add method, but contains any nested elements. I faced with this trying to add objects into DataGrid, but it reproduces for other object types.

How to Reproduce

Scenario 1 (DataGrid):

<DataGrid>
    <sys:Int32>1<sys:Int32>
</DataGrid>

Scenario 2 (Object):

<sys:Object>
    <sys:Int32>1<sys:Int32>
</sys:Object>

In both scenarios on compilling:

XamlTransformException: Internal compiler error: Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index (ResolveContentPropertyTransformer) Line 37, position 6.

ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
   at System.ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource)
   at System.Collections.Generic.List`1.get_Item(Int32 index)
   at XamlX.Transform.Transformers.ResolveContentPropertyTransformer.Transform(AstTransformationContext context, IXamlAstNode node) in D:\Git\AvaloniaUI\Avalonia\src\Markup\Avalonia.Markup.Xaml.Loader\xamlil.github\src\XamlX\Transform\Transformers\ResolveContentPropertyTransformer.cs
   ... <truncated>

Expected behavior

Compilation error No Content property or any Add methods found for type <type name>.

Additional info

More detaile here

Svelte and Xaml ❓

Hello,
I've been interested in svelte for a while. I also found avalonia for desktop programming. As a result of my research, I realized that axaml is an extension that belongs to this repository. While asking myself why a different xaml engine is needed. I found out that xamlx engine compiles IL code on ast. The same logic is valid in svelte, the room generates pure javascript file through ast code.
I wonder if I can generate xaml using xamlx and svelte?

Svelte Compiler

Converting xaml using javascript is a silly idea, of course, but I'm asking because I'm curious. Excuse me for my ignorance.

Add x:Shared attribute support

https://docs.microsoft.com/en-US/dotnet/desktop-wpf/xaml-services/xshared-attribute

This should enable setting attached behaviors from styles and probably enable setting ContextMenu from style too.

Current status:

        <Style Selector="TextBlock">
            <Setter Property="(i:Interaction.Behaviors)">
                <i:BehaviorCollection>
                    <behaviors:CheckParent/>
                </i:BehaviorCollection>
            </Setter>
        </Style>

Error:

System.InvalidOperationException: An instance of a behavior cannot be attached to more than one object at a time.
   at Avalonia.Xaml.Interactivity.BehaviorCollection.Attach(AvaloniaObject associatedObject)

Solution:

        <Style Selector="TextBlock" x:Shared="False">
            <Setter Property="(i:Interaction.Behaviors)">
                <i:BehaviorCollection>
                    <behaviors:CheckParent/>
                </i:BehaviorCollection>
            </Setter>
        </Style>

Reference:

https://docs.microsoft.com/en-US/dotnet/desktop-wpf/xaml-services/xshared-attribute

[Discussion] How tightly is this coupled to IL?

Hey @kekekeks, I'm looking through the architecture of this and wondering how tightly coupled to generating IL this is? As you know, I'm trying to get an effort started around unifying xaml tooling across all platforms. Both PresentationBuildTasks (WPF) and the UWP markup compiler have tight dependencies on the platforms, so what you've done here is incredibly interesting to me :).

With WinUI, we have c++ customers to support, so we can't depend on IL. I also have a feeling we'd need a way to switch out backends so we could continue to generate BAML for WPF and XBF for UWP, IL for Avalonia, etc.

Also, and this might just be me, but all the IXamlIL* types are hard to read, mostly because of the lIL letters in succession. It also makes me think that the whole thing is tightly coupled to IL, which I'm sure is not true, but it's also hard to get out of my head :)

IXamlMethod Generic definition

HI,
in the pr AvaloniaUI/Avalonia#15274. I have need to retrieve Interactive.AddHandler<TEventArgs> method. To do this, I tried using IXamlType.FindMethod and checking if the method name is AddHandler`1 without success.

After investigation I found following workaround

https://github.com/AvaloniaUI/Avalonia/blob/3f82e64c469198d3e80557b7c3c5071a8c29d806/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs#L155-L163

                AddHandlerT = Interactive.FindMethod(m => m.IsPublic
                    && !m.IsStatic
                    && m.Name == "AddHandler"
                    && m.Parameters.Count == 4
                    && RoutedEvent.IsAssignableFrom(m.Parameters[0])
                    && m.Parameters[0].GenericArguments?.Count == 1 // This is specific this case  workaround to check is generici method
                    && (cfg.WellKnownTypes.Delegate).IsAssignableFrom(m.Parameters[1])
                    && m.Parameters[2].IsEnum
                    && m.Parameters[3].Equals(cfg.WellKnownTypes.Boolean) == true

I would like to make a PR that makes it easier to identify the generic method. There are a few possibilities:

  • Add `n to the end of name of generic method, where n is number of generic arguments
  • Add property IsGenericDef to IXamlMethod
  • Expose GenericArguments and GenericParameters
  • All three previous proposed solutions

What do you think is the best solution?

TypeConverter not respected on primitive type.

Something like the following doesn't work:

[TypeConverter(typeof(SampleValuesConverter))]
public int SampleValues
{
    get { return (int)GetValue(SampleValuesProperty); }
    set { SetValue(SampleValuesProperty, value); }
}

The type converter isn't recognized. 3dd1407 added support for TypeConverter on properties but seems that the check is done at the very end, after XamlX has tried to convert the string to an int directly (and failed).

What the check File.WriteAllBytes("testasm.dll", data) in tests?

Hello!

I am thinking to add github actions and, accordingly, restore tests. I have updated the nuget packages and upgraded to netcoreapp 3.1. But the chair ran into the fact that my tests fall in this place

File.WriteAllBytes("testasm.dll", data);

With the following error

  Message: 
    System.IO.IOException : The process cannot access the file '.\XamlX\tests\CecilNetstandardTests\bin\Debug\netcoreapp3.1\testasm.dll' because it is being used by another process.
  Stack Trace: 
    FileStream.ValidateFileHandle(SafeFileHandle fileHandle)
    FileStream.CreateFileOpenHandle(FileMode mode, FileShare share, FileOptions options)
    FileStream.ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options)
    FileStream.ctor(String path, FileMode mode, FileAccess access, FileShare share)
    File.InternalWriteAllBytes(String path, Byte[] bytes)
    File.WriteAllBytes(String path, Byte[] bytes)
    CompilerTestBase.Compile(String xaml) line 75
    BasicCompilerTests.Compiler_Should_Compile_Simple_Xaml(Boolean populate) line 27

If I comment out, most of the tests pass (I don't think those test pairs are related to this). What this check?

P.S. If necessary, you can try, for example, using System.IO.Abstractions.TestingHelpers, writing something like this

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.