@ -21,7 +21,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
{
public static IXamlType UpdateCompiledBindingExtension ( AstTransformationContext context , XamlAstConstructableObjectNode binding , Func < IXamlType > startTypeResolver , IXamlType selfType )
{
IXamlType bindingResultType = null ;
IXamlType ? bindingResultType ;
if ( binding . Arguments . Count > 0 & & binding . Arguments [ 0 ] is ParsedBindingPathNode bindingPath )
{
var transformed = TransformBindingPath (
@ -90,8 +90,12 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
if ( GetPropertyType ( context , parentNode ) = = context . GetAvaloniaTypes ( ) . ICommand & & lastElement is XamlIlClrMethodPathElementNode methodPathElement )
{
IXamlMethod executeMethod = methodPathElement . Method ;
IXamlMethod canExecuteMethod = executeMethod . DeclaringType . FindMethod ( new FindMethodMethodSignature ( $"Can{executeMethod.Name}" , context . Configuration . WellKnownTypes . Boolean , context . Configuration . WellKnownTypes . Object ) ) ;
var executeMethod = methodPathElement . Method ;
var canExecuteMethod = executeMethod . DeclaringType . FindMethod ( new FindMethodMethodSignature (
$"Can{executeMethod.Name}" ,
context . Configuration . WellKnownTypes . Boolean ,
context . Configuration . WellKnownTypes . Object ) ) ;
List < string > dependsOnProperties = new ( ) ;
if ( canExecuteMethod is not null )
{
@ -99,7 +103,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
{
if ( attr . Type = = context . GetAvaloniaTypes ( ) . DependsOnAttribute )
{
dependsOnProperties . Add ( ( string ) attr . Parameters [ 0 ] ) ;
dependsOnProperties . Add ( ( string ) attr . Parameters [ 0 ] ! ) ;
}
}
}
@ -110,7 +114,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
return transformed ;
}
private static IXamlType GetPropertyType ( AstTransformationContext context , XamlPropertyAssignmentNode node )
private static IXamlType ? GetPropertyType ( AstTransformationContext context , XamlPropertyAssignmentNode node )
{
var setterType = context . GetAvaloniaTypes ( ) . Setter ;
@ -126,11 +130,11 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
. FirstOrDefault ( x = > x . Property . GetClrProperty ( ) . Name = = "Property" ) ;
var property = propertyAssignment ? . Values . FirstOrDefault ( ) as IXamlIlAvaloniaPropertyNode ;
if ( property . AvaloniaPropertyType is { } propertyType )
if ( property ? . AvaloniaPropertyType is { } propertyType )
return propertyType ;
}
return node . Property ? . Getter ? . ReturnType ;
return node . Property . Getter ? . ReturnType ;
}
private static XamlIlBindingPathNode TransformBindingPath ( AstTransformationContext context , IXamlLineInfo lineInfo , Func < IXamlType > startTypeResolver , IXamlType selfType , IEnumerable < BindingExpressionGrammar . INode > bindingExpression )
@ -150,7 +154,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
case BindingExpressionGrammar . StreamNode _ :
{
IXamlType targetType = targetTypeResolver ( ) ;
IXamlType observableType ;
IXamlType ? observableType ;
if ( targetType . GenericTypeDefinition ? . Equals ( context . Configuration . TypeSystem . FindType ( "System.IObservable`1" ) ) = = true )
{
observableType = targetType ;
@ -165,10 +169,13 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
nodes . Add ( new XamlIlStreamObservablePathElementNode ( observableType . GenericArguments [ 0 ] ) ) ;
break ;
}
bool foundTask = false ;
var taskType = context . Configuration . TypeSystem . GetType ( "System.Threading.Tasks.Task`1" ) ;
for ( var currentType = targetType ; currentType ! = null ; currentType = currentType . BaseType )
{
if ( currentType . GenericTypeDefinition . Equals ( context . Configuration . TypeSystem . GetType ( "System.Threading.Tasks.Task`1" ) ) )
if ( currentType . GenericTypeDefinition ? . Equals ( taskType ) = = true )
{
foundTask = true ;
nodes . Add ( new XamlIlStreamTaskPathElementNode ( currentType . GenericArguments [ 0 ] ) ) ;
@ -216,13 +223,13 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
break ;
}
IXamlProperty property = null ;
IXamlProperty ? property = null ;
foreach ( var currentType in TraverseTypeHierarchy ( targetType ) )
{
var defaultMemberAttribute = currentType . CustomAttributes . FirstOrDefault ( x = > x . Type . Namespace = = "System.Reflection" & & x . Type . Name = = "DefaultMemberAttribute" ) ;
if ( defaultMemberAttribute ! = null )
{
property = currentType . GetAllProperties ( ) . FirstOrDefault ( x = > x . Name = = ( string ) defaultMemberAttribute . Parameters [ 0 ] ) ;
property = currentType . GetAllProperties ( ) . FirstOrDefault ( x = > x . Name = = ( string ) defaultMemberAttribute . Parameters [ 0 ] ! ) ;
break ;
}
}
@ -255,8 +262,17 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
}
case BindingExpressionGrammar . AttachedPropertyNameNode attachedProp :
var avaloniaPropertyFieldName = attachedProp . PropertyName + "Property" ;
var avaloniaPropertyField = GetType ( attachedProp . Namespace , attachedProp . TypeName ) . GetAllFields ( ) . FirstOrDefault ( f = >
var propertyOwnerType = GetType ( attachedProp . Namespace , attachedProp . TypeName ) ;
var avaloniaPropertyField = propertyOwnerType . GetAllFields ( ) . FirstOrDefault ( f = >
f . IsStatic & & f . IsPublic & & f . Name = = avaloniaPropertyFieldName ) ;
if ( avaloniaPropertyField is null )
{
throw new XamlTransformException (
$"Unable to find {avaloniaPropertyFieldName} field on type {propertyOwnerType.GetFullName()}" ,
lineInfo ) ;
}
nodes . Add ( new XamlIlAvaloniaPropertyPropertyPathElementNode ( avaloniaPropertyField ,
XamlIlAvaloniaPropertyHelper . GetAvaloniaPropertyType ( avaloniaPropertyField , context . GetAvaloniaTypes ( ) , lineInfo ) ) ) ;
break ;
@ -305,7 +321,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
}
break ;
case BindingExpressionGrammar . NameNode elementName :
IXamlType elementType = null ;
IXamlType ? elementType = null ;
foreach ( var deferredContent in context . ParentNodes ( ) . OfType < NestedScopeMetadataNode > ( ) )
{
elementType = ScopeRegistrationFinder . GetTargetType ( deferredContent , elementName . Name ) ;
@ -340,7 +356,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
return new XamlIlBindingPathNode ( lineInfo , context . GetAvaloniaTypes ( ) . CompiledBindingPath , transformNodes , nodes ) ;
IXamlType GetType ( string ns , string name )
IXamlType GetType ( string? ns , string? name )
{
return TypeReferenceResolver . ResolveType ( context , $"{ns}:{name}" , false ,
lineInfo , true ) . GetClrType ( ) ;
@ -403,9 +419,9 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
string Name { get ; }
IXamlType TargetType { get ; set ; }
IXamlType ? TargetType { get ; set ; }
public static IXamlType GetTargetType ( IXamlAstNode namescopeRoot , string name )
public static IXamlType ? GetTargetType ( IXamlAstNode namescopeRoot , string name )
{
// If we start from the nested scope - skip it.
if ( namescopeRoot is NestedScopeMetadataNode scope )
@ -468,7 +484,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
public void Emit ( XamlIlEmitContext context , IXamlILEmitter codeGen )
{
codeGen . EmitCall ( context . GetAvaloniaTypes ( ) . CompiledBindingPathBuilder . Find Method( m = > m . Name = = "Not" ) ) ;
codeGen . EmitCall ( context . GetAvaloniaTypes ( ) . CompiledBindingPathBuilder . Get Method( m = > m . Name = = "Not" ) ) ;
}
}
@ -483,7 +499,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
public void Emit ( XamlIlEmitContext context , IXamlILEmitter codeGen )
{
codeGen . EmitCall ( context . GetAvaloniaTypes ( ) . CompiledBindingPathBuilder . Find Method( m = > m . Name = = "StreamObservable" ) . MakeGenericMethod ( new [ ] { Type } ) ) ;
codeGen . EmitCall ( context . GetAvaloniaTypes ( ) . CompiledBindingPathBuilder . Get Method( m = > m . Name = = "StreamObservable" ) . MakeGenericMethod ( new [ ] { Type } ) ) ;
}
}
@ -498,7 +514,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
public void Emit ( XamlIlEmitContext context , IXamlILEmitter codeGen )
{
codeGen . EmitCall ( context . GetAvaloniaTypes ( ) . CompiledBindingPathBuilder . Find Method( m = > m . Name = = "StreamTask" ) . MakeGenericMethod ( new [ ] { Type } ) ) ;
codeGen . EmitCall ( context . GetAvaloniaTypes ( ) . CompiledBindingPathBuilder . Get Method( m = > m . Name = = "StreamTask" ) . MakeGenericMethod ( new [ ] { Type } ) ) ;
}
}
@ -513,7 +529,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
public void Emit ( XamlIlEmitContext context , IXamlILEmitter codeGen )
{
codeGen . EmitCall ( context . GetAvaloniaTypes ( ) . CompiledBindingPathBuilder . Find Method( m = > m . Name = = "Self" ) ) ;
codeGen . EmitCall ( context . GetAvaloniaTypes ( ) . CompiledBindingPathBuilder . Get Method( m = > m . Name = = "Self" ) ) ;
}
}
@ -533,7 +549,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
{
codeGen . Ldtype ( Type )
. Ldc_I4 ( _l evel )
. EmitCall ( context . GetAvaloniaTypes ( ) . CompiledBindingPathBuilder . Find Method( m = > m . Name = = "Ancestor" ) ) ;
. EmitCall ( context . GetAvaloniaTypes ( ) . CompiledBindingPathBuilder . Get Method( m = > m . Name = = "Ancestor" ) ) ;
}
}
@ -553,7 +569,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
{
codeGen . Ldtype ( Type )
. Ldc_I4 ( _l evel )
. EmitCall ( context . GetAvaloniaTypes ( ) . CompiledBindingPathBuilder . Find Method( m = > m . Name = = "VisualAncestor" ) ) ;
. EmitCall ( context . GetAvaloniaTypes ( ) . CompiledBindingPathBuilder . Get Method( m = > m . Name = = "VisualAncestor" ) ) ;
}
}
@ -578,7 +594,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
. Ldloc ( context . ContextLocal )
. Ldfld ( scopeField )
. Ldstr ( _ name )
. EmitCall ( context . GetAvaloniaTypes ( ) . CompiledBindingPathBuilder . Find Method( m = > m . Name = = "ElementName" ) ) ;
. EmitCall ( context . GetAvaloniaTypes ( ) . CompiledBindingPathBuilder . Get Method( m = > m . Name = = "ElementName" ) ) ;
}
}
@ -594,7 +610,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
public void Emit ( XamlIlEmitContext context , IXamlILEmitter codeGen )
{
codeGen
. EmitCall ( context . GetAvaloniaTypes ( ) . CompiledBindingPathBuilder . Find Method( m = > m . Name = = "TemplatedParent" ) ) ;
. EmitCall ( context . GetAvaloniaTypes ( ) . CompiledBindingPathBuilder . Get Method( m = > m . Name = = "TemplatedParent" ) ) ;
}
}
@ -614,7 +630,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
context . Configuration . GetExtra < XamlIlPropertyInfoAccessorFactoryEmitter > ( )
. EmitLoadAvaloniaPropertyAccessorFactory ( context , codeGen ) ;
codeGen . EmitCall ( context . GetAvaloniaTypes ( )
. CompiledBindingPathBuilder . Find Method( m = > m . Name = = "Property" ) ) ;
. CompiledBindingPathBuilder . Get Method( m = > m . Name = = "Property" ) ) ;
}
public IXamlType Type { get ; }
@ -639,10 +655,10 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
codeGen
. EmitCall ( context . GetAvaloniaTypes ( )
. CompiledBindingPathBuilder . Find Method( m = > m . Name = = "Property" ) ) ;
. CompiledBindingPathBuilder . Get Method( m = > m . Name = = "Property" ) ) ;
}
public IXamlType Type = > _ property . Getter ? . ReturnType ? ? _ property . Setter ? . Parameters [ 0 ] ;
public IXamlType Type = > _ property . PropertyType ;
}
class XamlIlClrMethodPathElementNode : IXamlIlBindingPathElementNode
@ -659,7 +675,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
public void Emit ( XamlIlEmitContext context , IXamlILEmitter codeGen )
{
IXamlTypeBuilder < IXamlILEmitter > newDelegateTypeBuilder = null ;
IXamlTypeBuilder < IXamlILEmitter > ? newDelegateTypeBuilder = null ;
IXamlType specificDelegateType ;
if ( Method . ReturnType = = context . Configuration . WellKnownTypes . Void & & Method . Parameters . Count = = 0 )
{
@ -696,7 +712,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
. Ldtoken ( Method )
. Ldtoken ( specificDelegateType )
. EmitCall ( context . GetAvaloniaTypes ( )
. CompiledBindingPathBuilder . Find Method( m = > m . Name = = "Method" ) ) ;
. CompiledBindingPathBuilder . Get Method( m = > m . Name = = "Method" ) ) ;
newDelegateTypeBuilder ? . CreateType ( ) ;
}
@ -705,10 +721,14 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
class XamlIlClrMethodAsCommandPathElementNode : IXamlIlBindingPathElementNode
{
private readonly IXamlMethod _ executeMethod ;
private readonly IXamlMethod _ canExecuteMethod ;
private readonly IXamlMethod ? _ canExecuteMethod ;
private readonly IReadOnlyList < string > _d ependsOnProperties ;
public XamlIlClrMethodAsCommandPathElementNode ( IXamlType iCommandType , IXamlMethod executeMethod , IXamlMethod canExecuteMethod , IReadOnlyList < string > dependsOnProperties )
public XamlIlClrMethodAsCommandPathElementNode (
IXamlType iCommandType ,
IXamlMethod executeMethod ,
IXamlMethod ? canExecuteMethod ,
IReadOnlyList < string > dependsOnProperties )
{
Type = iCommandType ;
_ executeMethod = executeMethod ;
@ -716,7 +736,6 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
_d ependsOnProperties = dependsOnProperties ;
}
public IXamlType Type { get ; }
public void Emit ( XamlIlEmitContext context , IXamlILEmitter codeGen )
@ -770,7 +789,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
codeGen
. EmitCall ( context . GetAvaloniaTypes ( )
. CompiledBindingPathBuilder . Find Method( m = > m . Name = = "Command" ) ) ;
. CompiledBindingPathBuilder . Get Method( m = > m . Name = = "Command" ) ) ;
}
}
@ -810,10 +829,10 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
}
codeGen . EmitCall ( context . GetAvaloniaTypes ( )
. CompiledBindingPathBuilder . Find Method( m = > m . Name = = "Property" ) ) ;
. CompiledBindingPathBuilder . Get Method( m = > m . Name = = "Property" ) ) ;
}
public IXamlType Type = > _ property . Getter ? . ReturnType ? ? _ property . Setter ? . Parameters [ 0 ] ;
public IXamlType Type = > _ property . PropertyType ;
}
class XamlIlArrayIndexerPathElementNode : IXamlIlBindingPathElementNode
@ -853,10 +872,10 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
codeGen . Ldloc ( indices )
. Ldtype ( Type )
. EmitCall ( context . GetAvaloniaTypes ( )
. CompiledBindingPathBuilder . Find Method( m = > m . Name = = "ArrayElement" ) ) ;
. CompiledBindingPathBuilder . Get Method( m = > m . Name = = "ArrayElement" ) ) ;
}
public IXamlType Type = > _ arrayType . ArrayElementType ;
public IXamlType Type = > _ arrayType . ArrayElementType ! ;
}
class TypeCastPathElementNode : IXamlIlBindingPathElementNode
@ -870,7 +889,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
public void Emit ( XamlIlEmitContext context , IXamlILEmitter codeGen )
{
codeGen . EmitCall ( context . GetAvaloniaTypes ( ) . CompiledBindingPathBuilder . Find Method( m = > m . Name = = "TypeCast" ) . MakeGenericMethod ( new [ ] { Type } ) ) ;
codeGen . EmitCall ( context . GetAvaloniaTypes ( ) . CompiledBindingPathBuilder . Get Method( m = > m . Name = = "TypeCast" ) . MakeGenericMethod ( new [ ] { Type } ) ) ;
}
}
@ -906,7 +925,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
// of 1 to indicate that we don't want TemplatedParent compatibility hacks enabled.
codeGen
. Ldc_I4 ( 1 )
. Newobj ( types . CompiledBindingPathBuilder . Find Constructor( new ( ) { intType } ) ) ;
. Newobj ( types . CompiledBindingPathBuilder . Get Constructor( new ( ) { intType } ) ) ;
foreach ( var transform in _ transformElements )
{
@ -918,7 +937,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
element . Emit ( context , codeGen ) ;
}
codeGen . EmitCall ( types . CompiledBindingPathBuilder . Find Method( m = > m . Name = = "Build" ) ) ;
codeGen . EmitCall ( types . CompiledBindingPathBuilder . Get Method( m = > m . Name = = "Build" ) ) ;
return XamlILNodeEmitResult . Type ( 0 , types . CompiledBindingPath ) ;
}