44
55using System ;
66using System . Collections . Immutable ;
7+ using System . Threading ;
78using Microsoft . CodeAnalysis ;
9+ using Microsoft . CodeAnalysis . Diagnostics ;
10+
11+ #pragma warning disable CS1574
812
913namespace CommunityToolkit . Mvvm . SourceGenerators . Extensions ;
1014
@@ -13,6 +17,31 @@ namespace CommunityToolkit.Mvvm.SourceGenerators.Extensions;
1317/// </summary>
1418internal static class IncrementalGeneratorInitializationContextExtensions
1519{
20+ /// <inheritdoc cref="SyntaxValueProvider.ForAttributeWithMetadataName"/>
21+ public static IncrementalValuesProvider < T > ForAttributeWithMetadataNameAndOptions < T > (
22+ this IncrementalGeneratorInitializationContext context ,
23+ string fullyQualifiedMetadataName ,
24+ Func < SyntaxNode , CancellationToken , bool > predicate ,
25+ Func < GeneratorAttributeSyntaxContextWithOptions , CancellationToken , T > transform )
26+ {
27+ // Invoke 'ForAttributeWithMetadataName' normally, but just return the context directly
28+ IncrementalValuesProvider < GeneratorAttributeSyntaxContext > syntaxContext = context . SyntaxProvider . ForAttributeWithMetadataName (
29+ fullyQualifiedMetadataName ,
30+ predicate ,
31+ static ( context , token ) => context ) ;
32+
33+ // Do the same for the analyzer config options
34+ IncrementalValueProvider < AnalyzerConfigOptions > configOptions = context . AnalyzerConfigOptionsProvider . Select ( static ( provider , token ) => provider . GlobalOptions ) ;
35+
36+ // Merge the two and invoke the provided transform on these two values. Neither value
37+ // is equatable, meaning the pipeline will always re-run until this point. This is
38+ // intentional: we don't want any symbols or other expensive objects to be kept alive
39+ // across incremental steps, especially if they could cause entire compilations to be
40+ // rooted, which would significantly increase memory use and introduce more GC pauses.
41+ // In this specific case, flowing non equatable values in a pipeline is therefore fine.
42+ return syntaxContext . Combine ( configOptions ) . Select ( ( input , token ) => transform ( new GeneratorAttributeSyntaxContextWithOptions ( input . Left , input . Right ) , token ) ) ;
43+ }
44+
1645 /// <summary>
1746 /// Conditionally invokes <see cref="IncrementalGeneratorInitializationContext.RegisterSourceOutput{TSource}(IncrementalValueProvider{TSource}, Action{SourceProductionContext, TSource})"/>
1847 /// if the value produced by the input <see cref="IncrementalValueProvider{TValue}"/> is <see langword="true"/>.
0 commit comments