11
11
using Microsoft . CodeAnalysis ;
12
12
using Microsoft . CodeAnalysis . CSharp ;
13
13
using Microsoft . CodeAnalysis . CSharp . Syntax ;
14
- using static CommunityToolkit . Mvvm . SourceGenerators . Diagnostics . DiagnosticDescriptors ;
15
14
16
15
namespace CommunityToolkit . Mvvm . SourceGenerators ;
17
16
@@ -70,46 +69,40 @@ private protected TransitiveMembersGenerator(string attributeType, IEqualityComp
70
69
/// <inheritdoc/>
71
70
public void Initialize ( IncrementalGeneratorInitializationContext context )
72
71
{
73
- // Get all class declarations
74
- IncrementalValuesProvider < INamedTypeSymbol > typeSymbols =
72
+ // Gather all generation info, and any diagnostics
73
+ IncrementalValuesProvider < Result < ( HierarchyInfo Hierarchy , bool IsSealed , TInfo ? Info ) > > generationInfoWithErrors =
75
74
context . SyntaxProvider
76
75
. CreateSyntaxProvider (
77
76
static ( node , _ ) => node is ClassDeclarationSyntax { AttributeLists . Count : > 0 } ,
78
- static ( context , _ ) =>
77
+ ( context , token ) =>
79
78
{
80
79
if ( ! context . SemanticModel . Compilation . HasLanguageVersionAtLeastEqualTo ( LanguageVersion . CSharp8 ) )
81
80
{
82
81
return default ;
83
82
}
84
83
85
- return ( INamedTypeSymbol ) context . SemanticModel . GetDeclaredSymbol ( context . Node ) ! ;
86
- } )
87
- . Where ( static item => item is not null ) ! ;
84
+ INamedTypeSymbol typeSymbol = ( INamedTypeSymbol ) context . SemanticModel . GetDeclaredSymbol ( context . Node , token ) ! ;
88
85
89
- // Filter the types with the target attribute
90
- IncrementalValuesProvider < ( INamedTypeSymbol Symbol , AttributeData AttributeData ) > typeSymbolsWithAttributeData =
91
- typeSymbols
92
- . Select ( ( item , _ ) => (
93
- Symbol : item ,
94
- Attribute : item . GetAttributes ( ) . FirstOrDefault ( a => a . AttributeClass ? . HasFullyQualifiedName ( this . attributeType ) == true ) ) )
95
- . Where ( static item => item . Attribute is not null ) ! ;
86
+ // Filter the types with the target attribute
87
+ if ( ! typeSymbol . TryGetAttributeWithFullyQualifiedName ( this . attributeType , out AttributeData ? attributeData ) )
88
+ {
89
+ return default ;
90
+ }
96
91
97
- // Transform the input data
98
- IncrementalValuesProvider < ( INamedTypeSymbol Symbol , TInfo Info ) > typeSymbolsWithInfo = GetInfo ( context , typeSymbolsWithAttributeData ) ;
92
+ // Gather all generation info, and any diagnostics
93
+ TInfo ? info = ValidateTargetTypeAndGetInfo ( typeSymbol , attributeData , context . SemanticModel . Compilation , out ImmutableArray < Diagnostic > diagnostics ) ;
99
94
100
- // Gather all generation info, and any diagnostics
101
- IncrementalValuesProvider < Result < ( HierarchyInfo Hierarchy , bool IsSealed , TInfo Info ) > > generationInfoWithErrors =
102
- typeSymbolsWithInfo . Select ( ( item , _ ) =>
103
- {
104
- if ( ValidateTargetType ( item . Symbol , item . Info , out ImmutableArray < Diagnostic > diagnostics ) )
105
- {
106
- return new Result < ( HierarchyInfo , bool , TInfo ) > (
107
- ( HierarchyInfo . From ( item . Symbol ) , item . Symbol . IsSealed , item . Info ) ,
108
- ImmutableArray < Diagnostic > . Empty ) ;
109
- }
95
+ // If there are any diagnostics, there's no need to compute the hierarchy info at all, just return them
96
+ if ( diagnostics . Length > 0 )
97
+ {
98
+ return new Result < ( HierarchyInfo , bool , TInfo ? ) > ( default , diagnostics ) ;
99
+ }
100
+
101
+ HierarchyInfo hierarchy = HierarchyInfo . From ( typeSymbol ) ;
110
102
111
- return new Result < ( HierarchyInfo , bool , TInfo ) > ( default , diagnostics ) ;
112
- } ) ;
103
+ return new Result < ( HierarchyInfo , bool , TInfo ? ) > ( ( hierarchy , typeSymbol . IsSealed , info ) , diagnostics ) ;
104
+ } )
105
+ . Where ( static item => item is not null ) ! ;
113
106
114
107
// Emit the diagnostic, if needed
115
108
context . ReportDiagnostics ( generationInfoWithErrors . Select ( static ( item , _ ) => item . Errors ) ) ;
@@ -118,7 +111,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
118
111
IncrementalValuesProvider < ( HierarchyInfo Hierarchy , bool IsSealed , TInfo Info ) > generationInfo =
119
112
generationInfoWithErrors
120
113
. Where ( static item => item . Errors . IsEmpty )
121
- . Select ( static ( item , _ ) => item . Value )
114
+ . Select ( static ( item , _ ) => item . Value ) !
122
115
. WithComparers ( HierarchyInfo . Comparer . Default , EqualityComparer < bool > . Default , this . comparer ) ;
123
116
124
117
// Generate the required members
@@ -133,23 +126,15 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
133
126
}
134
127
135
128
/// <summary>
136
- /// Gathers info from a source <see cref="IncrementalValuesProvider{TValues}"/> input .
129
+ /// Validates the target type being processes, gets the info if possible and produces all necessary diagnostics .
137
130
/// </summary>
138
- /// <param name="context">The <see cref="IncrementalGeneratorInitializationContext"/> instance in use.</param>
139
- /// <param name="source">The source <see cref="IncrementalValuesProvider{TValues}"/> input.</param>
140
- /// <returns>A transformed <see cref="IncrementalValuesProvider{TValues}"/> instance with the gathered data.</returns>
141
- protected abstract IncrementalValuesProvider < ( INamedTypeSymbol Symbol , TInfo Info ) > GetInfo (
142
- IncrementalGeneratorInitializationContext context ,
143
- IncrementalValuesProvider < ( INamedTypeSymbol Symbol , AttributeData AttributeData ) > source ) ;
144
-
145
- /// <summary>
146
- /// Validates a target type being processed.
147
- /// </summary>
148
- /// <param name="typeSymbol">The <see cref="INamedTypeSymbol"/> instance for the target type.</param>
149
- /// <param name="info">The <typeparamref name="TInfo"/> instance with the current processing info.</param>
150
- /// <param name="diagnostics">The resulting diagnostics from the processing operation.</param>
151
- /// <returns>Whether or not the target type is valid and can be processed normally.</returns>
152
- protected abstract bool ValidateTargetType ( INamedTypeSymbol typeSymbol , TInfo info , out ImmutableArray < Diagnostic > diagnostics ) ;
131
+ /// <param name="typeSymbol">The <see cref="INamedTypeSymbol"/> instance currently being processed.</param>
132
+ /// <param name="attributeData">The <see cref="AttributeData"/> instance for the attribute used over <paramref name="typeSymbol"/>.</param>
133
+ /// <param name="compilation">The compilation that <paramref name="typeSymbol"/> belongs to.</param>
134
+ /// <param name="diagnostics">The resulting diagnostics, if any.</param>
135
+ /// <returns>The extracted info for the current type, if possible.</returns>
136
+ /// <remarks>If <paramref name="diagnostics"/> is empty, the returned info will always be ignored and no sources will be produced.</remarks>
137
+ protected abstract TInfo ? ValidateTargetTypeAndGetInfo ( INamedTypeSymbol typeSymbol , AttributeData attributeData , Compilation compilation , out ImmutableArray < Diagnostic > diagnostics ) ;
153
138
154
139
/// <summary>
155
140
/// Filters the <see cref="MemberDeclarationSyntax"/> nodes to generate from the input parsed tree.
0 commit comments