8
8
using System . Diagnostics . CodeAnalysis ;
9
9
using ILLink . RoslynAnalyzer . TrimAnalysis ;
10
10
using ILLink . Shared ;
11
- using ILLink . Shared . DataFlow ;
12
11
using ILLink . Shared . TrimAnalysis ;
13
12
using Microsoft . CodeAnalysis ;
14
- using Microsoft . CodeAnalysis . CSharp ;
15
- using Microsoft . CodeAnalysis . CSharp . Syntax ;
16
13
using Microsoft . CodeAnalysis . Diagnostics ;
17
- using Microsoft . CodeAnalysis . Operations ;
18
14
19
15
namespace ILLink . RoslynAnalyzer
20
16
{
@@ -106,85 +102,24 @@ public override void Initialize (AnalysisContext context)
106
102
// Examine generic instantiations in base types and interface list
107
103
context . RegisterSymbolAction ( context => {
108
104
var type = ( INamedTypeSymbol ) context . Symbol ;
109
- var location = GetPrimaryLocation ( type . Locations ) ;
110
105
// RUC on type doesn't silence DAM warnings about generic base/interface types.
111
106
// This knowledge lives in IsInRequiresUnreferencedCodeAttributeScope,
112
107
// which we still call for consistency here, but it is expected to return false.
113
108
if ( type . IsInRequiresUnreferencedCodeAttributeScope ( out _ ) )
114
109
return ;
115
110
116
- if ( type . BaseType is INamedTypeSymbol baseType ) {
117
- foreach ( var diagnostic in ProcessGenericParameters ( baseType , location ) )
118
- context . ReportDiagnostic ( diagnostic ) ;
119
- }
120
-
121
- foreach ( var interfaceType in type . Interfaces ) {
122
- foreach ( var diagnostic in ProcessGenericParameters ( interfaceType , location ) )
123
- context . ReportDiagnostic ( diagnostic ) ;
124
- }
125
- } , SymbolKind . NamedType ) ;
126
- // Examine generic instantiations in method return type and parameters.
127
- // This includes property getters and setters.
128
- context . RegisterSymbolAction ( context => {
129
- var method = ( IMethodSymbol ) context . Symbol ;
130
- if ( method . IsInRequiresUnreferencedCodeAttributeScope ( out _ ) )
131
- return ;
132
-
133
- var returnType = method . ReturnType ;
134
- foreach ( var diagnostic in ProcessGenericParameters ( returnType , GetPrimaryLocation ( method . Locations ) ) )
135
- context . ReportDiagnostic ( diagnostic ) ;
136
-
137
- foreach ( var parameter in method . Parameters ) {
138
- foreach ( var diagnostic in ProcessGenericParameters ( parameter . Type , GetPrimaryLocation ( parameter . Locations ) ) )
139
- context . ReportDiagnostic ( diagnostic ) ;
140
- }
141
- } , SymbolKind . Method ) ;
142
- // Examine generic instantiations in field type.
143
- context . RegisterSymbolAction ( context => {
144
- var field = ( IFieldSymbol ) context . Symbol ;
145
- if ( field . IsInRequiresUnreferencedCodeAttributeScope ( out _ ) )
146
- return ;
147
-
148
- foreach ( var diagnostic in ProcessGenericParameters ( field . Type , GetPrimaryLocation ( field . Locations ) ) )
149
- context . ReportDiagnostic ( diagnostic ) ;
150
- } , SymbolKind . Field ) ;
151
- // Examine generic instantiations in invocations of generically instantiated methods,
152
- // or methods on generically instantiated types.
153
- context . RegisterOperationAction ( context => {
154
- if ( context . ContainingSymbol . IsInRequiresUnreferencedCodeAttributeScope ( out _ ) )
155
- return ;
156
-
157
- var invocation = ( IInvocationOperation ) context . Operation ;
158
- var methodSymbol = invocation . TargetMethod ;
159
- foreach ( var diagnostic in ProcessMethodGenericParameters ( methodSymbol , invocation . Syntax . GetLocation ( ) ) )
160
- context . ReportDiagnostic ( diagnostic ) ;
161
- } , OperationKind . Invocation ) ;
162
- // Examine generic instantiations in delegate creation of generically instantiated methods.
163
- context . RegisterOperationAction ( context => {
164
- if ( context . ContainingSymbol . IsInRequiresUnreferencedCodeAttributeScope ( out _ ) )
165
- return ;
166
-
167
- var delegateCreation = ( IDelegateCreationOperation ) context . Operation ;
168
- if ( delegateCreation . Target is not IMethodReferenceOperation methodReference )
169
- return ;
111
+ var location = GetPrimaryLocation ( type . Locations ) ;
112
+ DiagnosticContext diagnosticContext = new ( location ) ;
170
113
171
- if ( methodReference . Method is not IMethodSymbol methodSymbol )
172
- return ;
173
- foreach ( var diagnostic in ProcessMethodGenericParameters ( methodSymbol , delegateCreation . Syntax . GetLocation ( ) ) )
174
- context . ReportDiagnostic ( diagnostic ) ;
175
- } , OperationKind . DelegateCreation ) ;
176
- // Examine generic instantiations in object creation of generically instantiated types.
177
- context . RegisterOperationAction ( context => {
178
- if ( context . ContainingSymbol . IsInRequiresUnreferencedCodeAttributeScope ( out _ ) )
179
- return ;
114
+ if ( type . BaseType is INamedTypeSymbol baseType )
115
+ GenericArgumentDataFlow . ProcessGenericArgumentDataFlow ( diagnosticContext , baseType ) ;
180
116
181
- var objectCreation = ( IObjectCreationOperation ) context . Operation ;
182
- if ( objectCreation . Type is not ITypeSymbol typeSymbol )
183
- return ;
117
+ foreach ( var interfaceType in type . Interfaces )
118
+ GenericArgumentDataFlow . ProcessGenericArgumentDataFlow ( diagnosticContext , interfaceType ) ;
184
119
185
- foreach ( var diagnostic in ProcessGenericParameters ( typeSymbol , objectCreation . Syntax . GetLocation ( ) ) )
120
+ foreach ( var diagnostic in diagnosticContext . Diagnostics )
186
121
context . ReportDiagnostic ( diagnostic ) ;
187
- } , OperationKind . ObjectCreation ) ;
122
+ } , SymbolKind . NamedType ) ;
188
123
context . RegisterSymbolAction ( context => {
189
124
VerifyMemberOnlyApplyToTypesOrStrings ( context , context . Symbol ) ;
190
125
VerifyDamOnPropertyAndAccessorMatch ( context , ( IMethodSymbol ) context . Symbol ) ;
@@ -202,66 +137,6 @@ public override void Initialize (AnalysisContext context)
202
137
} ) ;
203
138
}
204
139
205
- static IEnumerable < Diagnostic > ProcessMethodGenericParameters ( IMethodSymbol methodSymbol , Location location )
206
- {
207
- foreach ( var diagnostic in ProcessGenericParameters ( methodSymbol , location ) )
208
- yield return diagnostic ;
209
-
210
- if ( methodSymbol . IsStatic && methodSymbol . ContainingType is not null ) {
211
- foreach ( var diagnostic in ProcessGenericParameters ( methodSymbol . ContainingType , location ) )
212
- yield return diagnostic ;
213
- }
214
- }
215
-
216
- static IEnumerable < Diagnostic > ProcessGenericParameters ( ISymbol symbol , Location location )
217
- {
218
- // Avoid unnecessary execution if not NamedType or Method
219
- if ( symbol is not INamedTypeSymbol && symbol is not IMethodSymbol )
220
- yield break ;
221
-
222
- ImmutableArray < ITypeParameterSymbol > typeParams = default ;
223
- ImmutableArray < ITypeSymbol > typeArgs = default ;
224
- switch ( symbol ) {
225
- case INamedTypeSymbol type :
226
- typeParams = type . TypeParameters ;
227
- typeArgs = type . TypeArguments ;
228
- break ;
229
- case IMethodSymbol targetMethod :
230
- typeParams = targetMethod . TypeParameters ;
231
- typeArgs = targetMethod . TypeArguments ;
232
- break ;
233
- }
234
-
235
- if ( typeParams != null ) {
236
- Debug . Assert ( typeParams . Length == typeArgs . Length ) ;
237
-
238
- for ( int i = 0 ; i < typeParams . Length ; i ++ ) {
239
- // Syntax like typeof (Foo<>) will have an ErrorType as the type argument.
240
- // These uninstantiated generics should not produce warnings.
241
- if ( typeArgs [ i ] . Kind == SymbolKind . ErrorType )
242
- continue ;
243
- var sourceValue = SingleValueExtensions . FromTypeSymbol ( typeArgs [ i ] ) ! ;
244
- var targetValue = new GenericParameterValue ( typeParams [ i ] ) ;
245
- foreach ( var diagnostic in GetDynamicallyAccessedMembersDiagnostics ( sourceValue , targetValue , location ) )
246
- yield return diagnostic ;
247
- }
248
- }
249
- }
250
-
251
- static List < Diagnostic > GetDynamicallyAccessedMembersDiagnostics ( SingleValue sourceValue , SingleValue targetValue , Location location )
252
- {
253
- // The target should always be an annotated value, but the visitor design currently prevents
254
- // declaring this in the type system.
255
- if ( targetValue is not ValueWithDynamicallyAccessedMembers targetWithDynamicallyAccessedMembers )
256
- throw new NotImplementedException ( ) ;
257
-
258
- var diagnosticContext = new DiagnosticContext ( location ) ;
259
- var requireDynamicallyAccessedMembersAction = new RequireDynamicallyAccessedMembersAction ( diagnosticContext , default ( ReflectionAccessAnalyzer ) ) ;
260
- requireDynamicallyAccessedMembersAction . Invoke ( sourceValue , targetWithDynamicallyAccessedMembers ) ;
261
-
262
- return diagnosticContext . Diagnostics ;
263
- }
264
-
265
140
static void VerifyMemberOnlyApplyToTypesOrStrings ( SymbolAnalysisContext context , ISymbol member )
266
141
{
267
142
var location = GetPrimaryLocation ( member . Locations ) ;
0 commit comments