1
1
using System ;
2
2
using System . Collections . Generic ;
3
+ using System . Diagnostics ;
3
4
using System . IO ;
4
5
using System . Linq ;
5
6
using System . Reflection ;
@@ -44,20 +45,25 @@ public void Initialize(IncrementalGeneratorInitializationContext initContext)
44
45
var xmlnsDefinitionsProvider = initContext . CompilationProvider
45
46
. Select ( GetAssemblyAttributes ) ;
46
47
48
+ var typeCacheProvider = initContext . CompilationProvider
49
+ . Select ( GetTypeCache ) ;
50
+
47
51
var sourceProvider = projectItemProvider
48
52
. Combine ( xmlnsDefinitionsProvider )
53
+ . Combine ( typeCacheProvider )
49
54
. Combine ( initContext . CompilationProvider )
50
55
. Select ( static ( t , _ ) => ( t . Left . Left , t . Left . Right , t . Right ) ) ;
51
56
52
57
initContext . RegisterSourceOutput ( sourceProvider , static ( sourceProductionContext , provider ) =>
53
58
{
54
- var ( projectItem , caches , compilation ) = provider ;
59
+ var ( ( projectItem , xmlnsCache ) , typeCache , compilation ) = provider ;
55
60
if ( projectItem == null )
56
61
return ;
62
+
57
63
switch ( projectItem . Kind )
58
64
{
59
65
case "Xaml" :
60
- GenerateXamlCodeBehind ( projectItem , compilation , sourceProductionContext , caches ) ;
66
+ GenerateXamlCodeBehind ( projectItem , compilation , sourceProductionContext , xmlnsCache , typeCache ) ;
61
67
break ;
62
68
case "Css" :
63
69
GenerateCssCodeBehind ( projectItem , sourceProductionContext ) ;
@@ -137,7 +143,12 @@ static AssemblyCaches GetAssemblyAttributes(Compilation compilation, Cancellatio
137
143
return new AssemblyCaches ( xmlnsDefinitions , internalsVisible ) ;
138
144
}
139
145
140
- static void GenerateXamlCodeBehind ( ProjectItem projItem , Compilation compilation , SourceProductionContext context , AssemblyCaches caches )
146
+ static IDictionary < XmlType , string > GetTypeCache ( Compilation compilation , CancellationToken cancellationToken )
147
+ {
148
+ return new Dictionary < XmlType , string > ( ) ;
149
+ }
150
+
151
+ static void GenerateXamlCodeBehind ( ProjectItem projItem , Compilation compilation , SourceProductionContext context , AssemblyCaches caches , IDictionary < XmlType , string > typeCache )
141
152
{
142
153
var text = projItem . AdditionalText . GetText ( context . CancellationToken ) ;
143
154
if ( text == null )
@@ -149,7 +160,7 @@ static void GenerateXamlCodeBehind(ProjectItem projItem, Compilation compilation
149
160
return ;
150
161
var uid = Crc64 . ComputeHashString ( $ "{ compilation . AssemblyName } .{ itemName } ") ;
151
162
152
- if ( ! TryParseXaml ( text , uid , compilation , caches , context . CancellationToken , projItem . TargetFramework , out var accessModifier , out var rootType , out var rootClrNamespace , out var generateDefaultCtor , out var addXamlCompilationAttribute , out var hideFromIntellisense , out var XamlResourceIdOnly , out var baseType , out var namedFields , out var parseException ) )
163
+ if ( ! TryParseXaml ( text , uid , compilation , caches , typeCache , context . CancellationToken , projItem . TargetFramework , out var accessModifier , out var rootType , out var rootClrNamespace , out var generateDefaultCtor , out var addXamlCompilationAttribute , out var hideFromIntellisense , out var XamlResourceIdOnly , out var baseType , out var namedFields , out var parseException ) )
153
164
{
154
165
if ( parseException != null )
155
166
{
@@ -237,7 +248,7 @@ static void GenerateXamlCodeBehind(ProjectItem projItem, Compilation compilation
237
248
context . AddSource ( hintName , SourceText . From ( sb . ToString ( ) , Encoding . UTF8 ) ) ;
238
249
}
239
250
240
- static bool TryParseXaml ( SourceText text , string uid , Compilation compilation , AssemblyCaches caches , CancellationToken cancellationToken , string ? targetFramework , out string ? accessModifier , out string ? rootType , out string ? rootClrNamespace , out bool generateDefaultCtor , out bool addXamlCompilationAttribute , out bool hideFromIntellisense , out bool xamlResourceIdOnly , out string ? baseType , out IEnumerable < ( string , string , string ) > ? namedFields , out Exception ? exception )
251
+ static bool TryParseXaml ( SourceText text , string uid , Compilation compilation , AssemblyCaches caches , IDictionary < XmlType , string > typeCache , CancellationToken cancellationToken , string ? targetFramework , out string ? accessModifier , out string ? rootType , out string ? rootClrNamespace , out bool generateDefaultCtor , out bool addXamlCompilationAttribute , out bool hideFromIntellisense , out bool xamlResourceIdOnly , out string ? baseType , out IEnumerable < ( string , string , string ) > ? namedFields , out Exception ? exception )
241
252
{
242
253
cancellationToken . ThrowIfCancellationRequested ( ) ;
243
254
@@ -320,9 +331,9 @@ static bool TryParseXaml(SourceText text, string uid, Compilation compilation, A
320
331
return true ;
321
332
}
322
333
323
- namedFields = GetNamedFields ( root , nsmgr , compilation , caches , cancellationToken ) ;
334
+ namedFields = GetNamedFields ( root , nsmgr , compilation , caches , typeCache , cancellationToken ) ;
324
335
var typeArguments = GetAttributeValue ( root , "TypeArguments" , XamlParser . X2006Uri , XamlParser . X2009Uri ) ;
325
- baseType = GetTypeName ( new XmlType ( root . NamespaceURI , root . LocalName , typeArguments != null ? TypeArgumentsParser . ParseExpression ( typeArguments , nsmgr , null ) : null ) , compilation , caches ) ;
336
+ baseType = GetTypeName ( new XmlType ( root . NamespaceURI , root . LocalName , typeArguments != null ? TypeArgumentsParser . ParseExpression ( typeArguments , nsmgr , null ) : null ) , compilation , caches , typeCache ) ;
326
337
327
338
// x:ClassModifier attribute
328
339
var classModifier = GetAttributeValue ( root , "ClassModifier" , XamlParser . X2006Uri , XamlParser . X2009Uri ) ;
@@ -345,7 +356,7 @@ static bool GetXamlCompilationProcessingInstruction(XmlDocument xmlDoc)
345
356
return true ;
346
357
}
347
358
348
- static IEnumerable < ( string name , string type , string accessModifier ) > GetNamedFields ( XmlNode root , XmlNamespaceManager nsmgr , Compilation compilation , AssemblyCaches caches , CancellationToken cancellationToken )
359
+ static IEnumerable < ( string name , string type , string accessModifier ) > GetNamedFields ( XmlNode root , XmlNamespaceManager nsmgr , Compilation compilation , AssemblyCaches caches , IDictionary < XmlType , string > typeCache , CancellationToken cancellationToken )
349
360
{
350
361
var xPrefix = nsmgr . LookupPrefix ( XamlParser . X2006Uri ) ?? nsmgr . LookupPrefix ( XamlParser . X2009Uri ) ;
351
362
if ( xPrefix == null )
@@ -371,13 +382,17 @@ static bool GetXamlCompilationProcessingInstruction(XmlDocument xmlDoc)
371
382
var accessModifier = fieldModifier ? . ToLowerInvariant ( ) . Replace ( "notpublic" , "internal" ) ?? "private" ; //notpublic is WPF for internal
372
383
if ( ! new [ ] { "private" , "public" , "internal" , "protected" } . Contains ( accessModifier ) ) //quick validation
373
384
accessModifier = "private" ;
374
- yield return ( name ?? "" , GetTypeName ( xmlType , compilation , caches ) , accessModifier ) ;
385
+ yield return ( name ?? "" , GetTypeName ( xmlType , compilation , caches , typeCache ) , accessModifier ) ;
375
386
}
376
387
}
377
388
378
- static string GetTypeName ( XmlType xmlType , Compilation compilation , AssemblyCaches caches )
389
+ static string GetTypeName ( XmlType xmlType , Compilation compilation , AssemblyCaches caches , IDictionary < XmlType , string > typeCache )
379
390
{
380
- string returnType ;
391
+ if ( typeCache . TryGetValue ( xmlType , out string returnType ) )
392
+ {
393
+ return returnType ;
394
+ }
395
+
381
396
var ns = GetClrNamespace ( xmlType . NamespaceUri ) ;
382
397
if ( ns != null )
383
398
returnType = $ "{ ns } .{ xmlType . Name } ";
@@ -388,9 +403,11 @@ static string GetTypeName(XmlType xmlType, Compilation compilation, AssemblyCach
388
403
}
389
404
390
405
if ( xmlType . TypeArguments != null )
391
- returnType = $ "{ returnType } <{ string . Join ( ", " , xmlType . TypeArguments . Select ( typeArg => GetTypeName ( typeArg , compilation , caches ) ) ) } >";
406
+ returnType = $ "{ returnType } <{ string . Join ( ", " , xmlType . TypeArguments . Select ( typeArg => GetTypeName ( typeArg , compilation , caches , typeCache ) ) ) } >";
392
407
393
- return $ "global::{ returnType } ";
408
+ returnType = $ "global::{ returnType } ";
409
+ typeCache [ xmlType ] = returnType ;
410
+ return returnType ;
394
411
}
395
412
396
413
static string ? GetClrNamespace ( string namespaceuri )
0 commit comments