@@ -15,11 +15,11 @@ internal class MockGenerator : ISourceGenerator, IDisposable {
15
15
private static class DiagnosticDescriptors {
16
16
#pragma warning disable RS2008 // Enable analyzer release tracking
17
17
public static readonly DiagnosticDescriptor SingleMockFailedToGenerate = new (
18
- "SM0001 " , "Failed to generate a single mock" , "Failed to generate mock for {0}: {1}" ,
18
+ "SourceMock001 " , "Failed to generate a single mock" , "Failed to generate mock for {0}: {1}" ,
19
19
"Generation" , DiagnosticSeverity . Warning , isEnabledByDefault : true
20
20
) ;
21
21
public static readonly DiagnosticDescriptor RegexPatternFailedToParse = new (
22
- "SM0011 " , "Regex pattern is not a valid regex" , "Regex pattern \" {0}\" cannot be parsed: {1}" ,
22
+ "SourceMock002 " , "Regex pattern is not a valid regex" , "Regex pattern \" {0}\" cannot be parsed: {1}" ,
23
23
"Generation" , DiagnosticSeverity . Error , isEnabledByDefault : true
24
24
) ;
25
25
#pragma warning restore RS2008 // Enable analyzer release tracking
@@ -44,13 +44,7 @@ public void Execute(GeneratorExecutionContext context) {
44
44
var attributes = context . Compilation . Assembly . GetAttributes ( ) ;
45
45
GeneratorLog . Log ( "Get attributes finished" ) ;
46
46
foreach ( var attribute in attributes ) {
47
- if ( attribute . AttributeClass is not { Name : KnownTypes . GenerateMocksForAssemblyOfAttribute . Name } attributeClass )
48
- continue ;
49
-
50
- if ( ! KnownTypes . GenerateMocksForAssemblyOfAttribute . NamespaceMatches ( attributeClass . ContainingNamespace ) )
51
- continue ;
52
-
53
- GenerateMocksForAttributeTargetAssembly ( attribute , context ) ;
47
+ ProcessAssemblyAttribute ( attribute , context ) ;
54
48
}
55
49
}
56
50
catch ( Exception ex ) {
@@ -60,6 +54,33 @@ public void Execute(GeneratorExecutionContext context) {
60
54
GeneratorLog . Log ( "MockGenerator.Execute finished" ) ;
61
55
}
62
56
57
+ private void ProcessAssemblyAttribute ( AttributeData attribute , in GeneratorExecutionContext context ) {
58
+ if ( attribute . AttributeClass is not { } attributeClass )
59
+ return ;
60
+
61
+ switch ( attributeClass . Name ) {
62
+ case KnownTypes . GenerateMocksForAssemblyOfAttribute . Name :
63
+ if ( ! KnownTypes . GenerateMocksForAssemblyOfAttribute . NamespaceMatches ( attributeClass . ContainingNamespace ) )
64
+ return ;
65
+ GenerateMocksForAttributeTargetAssembly ( attribute , context ) ;
66
+ break ;
67
+
68
+ case KnownTypes . GenerateMocksForTypesAttribute . Name :
69
+ if ( ! KnownTypes . GenerateMocksForTypesAttribute . NamespaceMatches ( attributeClass . ContainingNamespace ) )
70
+ return ;
71
+
72
+ if ( attribute . ConstructorArguments . ElementAtOrDefault ( 0 ) is not { Kind : TypedConstantKind . Array , Values : var typeofConstants } )
73
+ return ;
74
+
75
+ foreach ( var typeofConstant in typeofConstants ) {
76
+ if ( typeofConstant is not { Value : INamedTypeSymbol type } )
77
+ continue ;
78
+ GenerateMockForType ( new MockTarget ( type , GetFullTypeName ( type ) ) , assemblyCacheBuilder : null , context ) ;
79
+ }
80
+ break ;
81
+ }
82
+ }
83
+
63
84
[ PerformanceSensitive ( "" ) ]
64
85
private void GenerateMocksForAttributeTargetAssembly ( AttributeData attribute , in GeneratorExecutionContext context ) {
65
86
// intermediate code state? just in case
@@ -118,7 +139,9 @@ in GeneratorExecutionContext context
118
139
#pragma warning restore HAA0401
119
140
switch ( member ) {
120
141
case INamedTypeSymbol type :
121
- GenerateMockForTypeIfApplicable ( type , excludeRegex , assemblyCacheBuilder , context ) ;
142
+ if ( ! ShouldIncludeInMocksForAssembly ( type , excludeRegex , out var fullName , context ) )
143
+ continue ;
144
+ GenerateMockForType ( new MockTarget ( type , fullName ! ) , assemblyCacheBuilder , context ) ;
122
145
break ;
123
146
124
147
case INamespaceSymbol nested :
@@ -129,59 +152,45 @@ in GeneratorExecutionContext context
129
152
}
130
153
131
154
[ PerformanceSensitive ( "" ) ]
132
- private void GenerateMockForTypeIfApplicable (
155
+ private bool ShouldIncludeInMocksForAssembly (
133
156
INamedTypeSymbol type ,
134
157
Regex ? excludeRegex ,
135
- ImmutableArray < ( string , SourceText ) > . Builder assemblyCacheBuilder ,
158
+ out string ? fullName ,
136
159
in GeneratorExecutionContext context
137
160
) {
138
- if ( ! ShouldGenerateMockForTypeKind ( type , out var potentiallyLoadedMembers ) )
139
- return ;
161
+ fullName = null ;
162
+ if ( type . TypeKind != TypeKind . Interface )
163
+ return false ;
140
164
141
165
if ( type . DeclaredAccessibility != Accessibility . Public ) {
142
166
var isVisibleInternal = type . DeclaredAccessibility == Accessibility . Internal
143
167
&& type . ContainingAssembly . GivesAccessTo ( context . Compilation . Assembly ) ;
144
168
if ( ! isVisibleInternal )
145
- return ;
169
+ return false ;
146
170
}
147
171
148
- var fullName = type . ToDisplayString ( SymbolDisplayFormat . FullyQualifiedFormat ) ;
172
+ fullName = GetFullTypeName ( type ) ;
149
173
if ( excludeRegex != null && excludeRegex . IsMatch ( fullName ) )
150
- return ;
174
+ return false ;
151
175
152
- GenerateMockForType ( new MockTarget ( type , fullName , potentiallyLoadedMembers ) , assemblyCacheBuilder , context ) ;
176
+ return true ;
153
177
}
154
178
155
179
[ PerformanceSensitive ( "" ) ]
156
- private bool ShouldGenerateMockForTypeKind ( INamedTypeSymbol type , out ImmutableArray < ISymbol > ? members ) {
157
- members = null ;
158
- if ( type . TypeKind == TypeKind . Interface )
159
- return true ;
160
-
161
- if ( type . TypeKind == TypeKind . Class ) {
162
- if ( type . IsSealed )
163
- return false ;
164
-
165
- members = type . GetMembers ( ) ;
166
- foreach ( var member in members ) {
167
- if ( member . IsVirtual || member . IsAbstract )
168
- return true ;
169
- }
170
- }
171
-
172
- return false ;
180
+ private static string GetFullTypeName ( INamedTypeSymbol type ) {
181
+ return type . ToDisplayString ( SymbolDisplayFormat . FullyQualifiedFormat ) ;
173
182
}
174
183
175
184
[ PerformanceSensitive ( "" ) ]
176
185
private void GenerateMockForType (
177
186
MockTarget target ,
178
- ImmutableArray < ( string , SourceText ) > . Builder assemblyCacheBuilder ,
187
+ ImmutableArray < ( string , SourceText ) > . Builder ? assemblyCacheBuilder ,
179
188
in GeneratorExecutionContext context
180
189
) {
181
190
if ( _mockedTypeCache . TryGetValue ( target . Type , out var cached ) ) {
182
191
GeneratorLog . Log ( "Using cached mock for type " + target . FullTypeName ) ;
183
192
context . AddSource ( cached . name , cached . source ) ;
184
- assemblyCacheBuilder . Add ( cached ) ;
193
+ assemblyCacheBuilder ? . Add ( cached ) ;
185
194
return ;
186
195
}
187
196
@@ -204,7 +213,7 @@ in GeneratorExecutionContext context
204
213
var mockSource = SourceText . From ( mockContent , Encoding . UTF8 ) ;
205
214
context . AddSource ( mockFileName , mockSource ) ;
206
215
_mockedTypeCache . TryAdd ( target . Type , ( mockFileName , mockSource ) ) ;
207
- assemblyCacheBuilder . Add ( ( mockFileName , mockSource ) ) ;
216
+ assemblyCacheBuilder ? . Add ( ( mockFileName , mockSource ) ) ;
208
217
}
209
218
210
219
public void Dispose ( ) {
0 commit comments