11using System ;
22using System . CodeDom . Compiler ;
3+ using System . Collections . Concurrent ;
34using System . Collections . Generic ;
45using System . Collections . Immutable ;
56using System . Diagnostics ;
1011using Microsoft . CodeAnalysis . CSharp ;
1112using Microsoft . CodeAnalysis . CSharp . Syntax ;
1213using Microsoft . Maui . Controls . Xaml ;
14+ using Microsoft . Maui . Controls . SourceGen . TypeConverters ;
1315
1416namespace Microsoft . Maui . Controls . SourceGen ;
1517
@@ -20,38 +22,59 @@ static class NodeSGExtensions
2022
2123 public delegate bool ProvideValueDelegate ( IElementNode markupNode , SourceGenContext context , out ITypeSymbol ? returnType , out string value ) ;
2224
25+ // Lazy converter factory function
26+ static ConverterDelegate CreateLazyConverter < T > ( ) where T : ISGTypeConverter , new ( ) =>
27+ ( value , node , toType , context , parentVar ) =>
28+ lazyConverters . GetOrAdd ( typeof ( T ) , _ => new T ( ) ) . Convert ( value , node , toType , context , parentVar ) ;
29+
30+ static readonly ConcurrentDictionary < Type , ISGTypeConverter > lazyConverters = new ( ) ;
31+ static readonly ConcurrentDictionary < string , ISGTypeConverter > lazyRegistryConverters = new ( ) ;
32+
33+ // Lazy registry-based converter function (for non-source-gen converters)
34+ private static ConverterDelegate CreateLazyRegistryConverter ( string typeName ) =>
35+ ( value , node , toType , context , parentVar ) =>
36+ {
37+ var converter = lazyRegistryConverters . GetOrAdd ( typeName , name => TypeConverterRegistry . GetConverter ( name ) ! ) ;
38+ return converter ? . Convert ( value , node , toType , context , parentVar ) ?? "default" ;
39+ } ;
40+
41+ // Lazy enum converter
42+ private static readonly Lazy < EnumConverter > _lazyEnumConverter = new ( ( ) => new EnumConverter ( ) ) ;
43+
44+ private static string ConvertEnum ( string value , BaseNode node , ITypeSymbol toType , SourceGenContext context , LocalVariable ? parentVar = null ) =>
45+ _lazyEnumConverter . Value . Convert ( value , node , toType , context , parentVar ) ;
2346
2447 static Dictionary < ITypeSymbol , ( ConverterDelegate converter , ITypeSymbol returnType ) > GetKnownSGTypeConverters ( SourceGenContext context )
2548 => context . knownSGTypeConverters ??= new ( SymbolEqualityComparer . Default )
2649 {
27- { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Graphics.Converters.RectTypeConverter" ) ! , ( KnownTypeConverters . ConvertRect , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Graphics.Rect" ) ! ) } ,
28- { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Graphics.Converters.ColorTypeConverter" ) ! , ( KnownTypeConverters . ConvertColor , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Graphics.Color" ) ! ) } ,
29- { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Graphics.Converters.PointTypeConverter" ) ! , ( KnownTypeConverters . ConvertPoint , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Graphics.Point" ) ! ) } ,
30- { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Converters.ThicknessTypeConverter" ) ! , ( KnownTypeConverters . ConvertThickness , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Thickness" ) ! ) } ,
31- { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Converters.CornerRadiusTypeConverter" ) ! , ( KnownTypeConverters . ConvertCornerRadius , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.CornerRadius" ) ! ) } ,
32- { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Converters.EasingTypeConverter" ) ! , ( KnownTypeConverters . ConvertEasing , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Easing" ) ! ) } ,
33- { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Converters.FlexJustifyTypeConverter" ) ! , ( KnownTypeConverters . ConvertEnum , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Layouts.FlexJustify" ) ! ) } ,
34- { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Converters.FlexDirectionTypeConverter" ) ! , ( KnownTypeConverters . ConvertEnum , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Layouts.FlexDirection" ) ! ) } ,
35- { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Converters.FlexAlignContentTypeConverter" ) ! , ( KnownTypeConverters . ConvertEnum , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Layouts.FlexAlignContent" ) ! ) } ,
36- { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Converters.FlexAlignItemsTypeConverter" ) ! , ( KnownTypeConverters . ConvertEnum , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Layouts.FlexAlignItems" ) ! ) } ,
37- { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Converters.FlexAlignSelfTypeConverter" ) ! , ( KnownTypeConverters . ConvertEnum , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Layouts.FlexAlignSelf" ) ! ) } ,
38- { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Converters.FlexWrapTypeConverter" ) ! , ( KnownTypeConverters . ConvertEnum , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Layouts.FlexWrap" ) ! ) } ,
39- { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Converters.FlexBasisTypeConverter" ) ! , ( KnownTypeConverters . ConvertFlexBasis , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Layouts.FlexBasis" ) ! ) } ,
40- { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Controls.ColumnDefinitionCollectionTypeConverter" ) ! , ( KnownTypeConverters . ConvertColumnDefinitionCollection , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Controls.ColumnDefinitionCollection" ) ! ) } ,
41- { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Controls.FlowDirectionConverter" ) ! , ( KnownTypeConverters . ConvertFlowDirection , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.FlowDirection" ) ! ) } ,
42- { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Controls.FontSizeConverter" ) ! , ( KnownTypeConverters . ConvertFontSize , context . Compilation . GetTypeByMetadataName ( "System.Double" ) ! ) } ,
43- { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Controls.GridLengthTypeConverter" ) ! , ( KnownTypeConverters . ConvertGridLength , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.GridLength" ) ! ) } ,
44- { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Controls.ImageSourceConverter" ) ! , ( KnownTypeConverters . ConvertImageSource , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Controls.ImageSource" ) ! ) } ,
45- { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Controls.LayoutOptionsConverter" ) ! , ( KnownTypeConverters . ConvertLayoutOptions , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Controls.LayoutOptions" ) ! ) } ,
46- { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Controls.ListStringTypeConverter" ) ! , ( KnownTypeConverters . ConvertListString , context . Compilation . GetTypeByMetadataName ( "System.Collections.Generic.IList`1" ) ! . Construct ( context . Compilation . GetSpecialType ( SpecialType . System_String ) ) ! ) } ,
47- { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Controls.ResourceDictionary+RDSourceTypeConverter" ) ! , ( KnownTypeConverters . ConvertRDSource , context . Compilation . GetTypeByMetadataName ( "System.Uri" ) ! ) } ,
48- { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Controls.RowDefinitionCollectionTypeConverter" ) ! , ( KnownTypeConverters . ConvertRowDefinitionCollection , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Controls.RowDefinitionCollection" ) ! ) } ,
49- { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Controls.Shapes.PointCollectionConverter" ) ! , ( KnownTypeConverters . ConvertPointCollection , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Controls.PointCollection" ) ! ) } ,
50- { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Controls.Compatibility.ConstraintTypeConverter" ) ! , ( KnownTypeConverters . ConvertConstraint , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Controls.Compatibility.Constraint" ) ! ) } ,
50+ { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Graphics.Converters.RectTypeConverter" ) ! , ( CreateLazyConverter < RectConverter > ( ) , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Graphics.Rect" ) ! ) } ,
51+ { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Graphics.Converters.ColorTypeConverter" ) ! , ( CreateLazyConverter < ColorConverter > ( ) , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Graphics.Color" ) ! ) } ,
52+ { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Graphics.Converters.PointTypeConverter" ) ! , ( CreateLazyConverter < PointConverter > ( ) , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Graphics.Point" ) ! ) } ,
53+ { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Converters.ThicknessTypeConverter" ) ! , ( CreateLazyConverter < ThicknessConverter > ( ) , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Thickness" ) ! ) } ,
54+ { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Converters.CornerRadiusTypeConverter" ) ! , ( CreateLazyRegistryConverter ( "Microsoft.Maui.CornerRadius" ) , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.CornerRadius" ) ! ) } ,
55+ { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Converters.EasingTypeConverter" ) ! , ( CreateLazyRegistryConverter ( "Microsoft.Maui.Easing" ) , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Easing" ) ! ) } ,
56+ { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Converters.FlexJustifyTypeConverter" ) ! , ( ConvertEnum , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Layouts.FlexJustify" ) ! ) } ,
57+ { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Converters.FlexDirectionTypeConverter" ) ! , ( ConvertEnum , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Layouts.FlexDirection" ) ! ) } ,
58+ { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Converters.FlexAlignContentTypeConverter" ) ! , ( ConvertEnum , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Layouts.FlexAlignContent" ) ! ) } ,
59+ { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Converters.FlexAlignItemsTypeConverter" ) ! , ( ConvertEnum , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Layouts.FlexAlignItems" ) ! ) } ,
60+ { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Converters.FlexAlignSelfTypeConverter" ) ! , ( ConvertEnum , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Layouts.FlexAlignSelf" ) ! ) } ,
61+ { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Converters.FlexWrapTypeConverter" ) ! , ( ConvertEnum , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Layouts.FlexWrap" ) ! ) } ,
62+ { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Converters.FlexBasisTypeConverter" ) ! , ( CreateLazyRegistryConverter ( "Microsoft.Maui.Layouts.FlexBasis" ) , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Layouts.FlexBasis" ) ! ) } ,
63+ { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Controls.ColumnDefinitionCollectionTypeConverter" ) ! , ( CreateLazyRegistryConverter ( "Microsoft.Maui.Controls.ColumnDefinitionCollection" ) , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Controls.ColumnDefinitionCollection" ) ! ) } ,
64+ { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Controls.FlowDirectionConverter" ) ! , ( CreateLazyRegistryConverter ( "Microsoft.Maui.FlowDirection" ) , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.FlowDirection" ) ! ) } ,
65+ { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Controls.FontSizeConverter" ) ! , ( CreateLazyRegistryConverter ( "System.Double" ) , context . Compilation . GetTypeByMetadataName ( "System.Double" ) ! ) } ,
66+ { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Controls.GridLengthTypeConverter" ) ! , ( CreateLazyConverter < GridLengthConverter > ( ) , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.GridLength" ) ! ) } ,
67+ { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Controls.ImageSourceConverter" ) ! , ( CreateLazyRegistryConverter ( "Microsoft.Maui.Controls.ImageSource" ) , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Controls.ImageSource" ) ! ) } ,
68+ { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Controls.LayoutOptionsConverter" ) ! , ( CreateLazyRegistryConverter ( "Microsoft.Maui.Controls.LayoutOptions" ) , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Controls.LayoutOptions" ) ! ) } ,
69+ { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Controls.ListStringTypeConverter" ) ! , ( CreateLazyRegistryConverter ( "System.Collections.Generic.IList`1[System.String]" ) , context . Compilation . GetTypeByMetadataName ( "System.Collections.Generic.IList`1" ) ! . Construct ( context . Compilation . GetSpecialType ( SpecialType . System_String ) ) ! ) } ,
70+ { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Controls.ResourceDictionary+RDSourceTypeConverter" ) ! , ( CreateLazyRegistryConverter ( "System.Uri" ) , context . Compilation . GetTypeByMetadataName ( "System.Uri" ) ! ) } ,
71+ { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Controls.RowDefinitionCollectionTypeConverter" ) ! , ( CreateLazyRegistryConverter ( "Microsoft.Maui.Controls.RowDefinitionCollection" ) , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Controls.RowDefinitionCollection" ) ! ) } ,
72+ { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Controls.Shapes.PointCollectionConverter" ) ! , ( CreateLazyRegistryConverter ( "Microsoft.Maui.Controls.PointCollection" ) , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Controls.PointCollection" ) ! ) } ,
73+ { context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Controls.Compatibility.ConstraintTypeConverter" ) ! , ( CreateLazyRegistryConverter ( "Microsoft.Maui.Controls.Compatibility.Constraint" ) , context . Compilation . GetTypeByMetadataName ( "Microsoft.Maui.Controls.Compatibility.Constraint" ) ! ) } ,
5174
5275 // TODO: PathFigureCollectionConverter (used for PathGeometry and StrokeShape) is very complex, skipping for now, apart from that one all other shapes work though
53- //{ context.Compilation.GetTypeByMetadataName("Microsoft.Maui.Controls.Shapes.PathGeometryConverter")!, (KnownTypeConverters.ConvertPathGeometry , context.Compilation.GetTypeByMetadataName("Microsoft.Maui.Controls.Shapes.Geometry")!) },
54- //{ context.Compilation.GetTypeByMetadataName("Microsoft.Maui.Controls.Shapes.StrokeShapeTypeConverter")!, (KnownTypeConverters.ConvertStrokeShape , context.Compilation.GetTypeByMetadataName("Microsoft.Maui.Controls.Shapes.Shape")!) },
76+ //{ context.Compilation.GetTypeByMetadataName("Microsoft.Maui.Controls.Shapes.PathGeometryConverter")!, (CreateRegistryConverter("Microsoft.Maui.Controls.Shapes.Geometry") , context.Compilation.GetTypeByMetadataName("Microsoft.Maui.Controls.Shapes.Geometry")!) },
77+ //{ context.Compilation.GetTypeByMetadataName("Microsoft.Maui.Controls.Shapes.StrokeShapeTypeConverter")!, (CreateRegistryConverter("Microsoft.Maui.Controls.Shapes.Shape") , context.Compilation.GetTypeByMetadataName("Microsoft.Maui.Controls.Shapes.Shape")!) },
5578 } ;
5679
5780 public static Dictionary < ITypeSymbol , ProvideValueDelegate > GetKnownValueProviders ( SourceGenContext context )
0 commit comments