@@ -37,6 +37,16 @@ public static void Process(AssemblyDefinition assemblyDef)
3737 Fix_LambdaFrame_Constructor ( method ) ;
3838 }
3939 }
40+
41+ var sourceAssemblySymbol = module . GetType ( "Microsoft.CodeAnalysis.CSharp.Symbols.SourceAssemblySymbol" ) ;
42+ if ( sourceAssemblySymbol != null )
43+ {
44+ foreach ( var method in sourceAssemblySymbol . Methods )
45+ {
46+ if ( method . Name == "GetUnusedFieldWarnings" )
47+ Fix_SourceAssemblySymbol_GetUnusedFieldWarnings ( method ) ;
48+ }
49+ }
4050 }
4151 }
4252
@@ -237,5 +247,66 @@ private static void Fix_GeneratedNames_MakeLambdaMethodName(MethodDefinition met
237247 il . InsertBefore ( baseInst , il . Create ( OpCodes . Ldstr , "<>m__" ) ) ;
238248 il . InsertBefore ( baseInst2 , il . Create ( OpCodes . Call , concat ) ) ;
239249 }
250+
251+ private static void Fix_SourceAssemblySymbol_GetUnusedFieldWarnings ( MethodDefinition method )
252+ {
253+ // Goal:
254+ // Add "Skip CS0649 warning for a field has attributes" to GetUnusedFieldWarnings in SourceAssemblySymbol
255+ //
256+ // How for Roslyn:
257+ // Add following statements after "if (!field.CanBeReferencedByName) { continue; }"
258+ // if (!field.GetAttributes().IsEmpty) { continue; }
259+ //
260+ // How for IL:
261+ // IL_0078: ldloc.s 4
262+ // IL_007a: callvirt instance bool Microsoft.CodeAnalysis.CSharp.Symbol::get_CanBeReferencedByName()
263+ // IL_007f: brfalse IL_018b
264+ // >> IL_?: ldloc.s 4
265+ // >> IL_?: callvirt instance valuetype ImmutableArray<CSharpAttributeData> Microsoft.CodeAnalysis.CSharp.Symbol::GetAttributes()
266+ // >> IL_?: stloc 13
267+ // >> IL_?: ldloca.s 13
268+ // >> IL_?: call instance bool valuetype ImmutableArray<CSharpAttributeData>::get_IsEmpty()
269+ // >> IL_?: brfalse IL_018b
270+
271+ var il = method . Body . GetILProcessor ( ) ;
272+ var attributeDataType = method . Module . GetType ( "Microsoft.CodeAnalysis.CSharp.Symbols.CSharpAttributeData" ) ;
273+
274+ // find Methods
275+ var symbolType = method . Module . GetType ( "Microsoft.CodeAnalysis.CSharp.Symbol" ) ;
276+ var symbolGetAttributesMethod = symbolType . GetMethod ( "GetAttributes" ) ;
277+ var symbolGetAttributes = method . Module . Import ( symbolGetAttributesMethod ) ;
278+ var symbolReturnType = ( GenericInstanceType ) symbolGetAttributesMethod . ReturnType ;
279+ var symbolIsEmptyMethod = symbolReturnType . Resolve ( ) . GetMethod ( "get_IsEmpty" ) ;
280+ var symbolIsEmptyMethodRef = method . Module . Import ( symbolIsEmptyMethod ) ;
281+ var symbolIsEmpty = symbolIsEmptyMethodRef . MakeGeneric ( symbolReturnType . GenericArguments . ToArray ( ) ) ;
282+
283+ // Add local var of ImmutableArray<CSharpAttributeData>
284+ var attributeArrayType = new GenericInstanceType ( symbolReturnType . ElementType ) ;
285+ var attributeArrayLocalIndex = il . Body . Variables . Count ;
286+ attributeArrayType . GenericArguments . Add ( attributeDataType ) ;
287+ il . Body . Variables . Add ( new VariableDefinition ( attributeArrayType ) ) ;
288+
289+ for ( var i = 0 ; i < il . Body . Instructions . Count ; i ++ )
290+ {
291+ var inst = il . Body . Instructions [ i ] ;
292+ if ( inst . OpCode . Code == Code . Callvirt && ( ( MethodReference ) inst . Operand ) . Name == "get_CanBeReferencedByName" )
293+ {
294+ if ( inst . Previous . OpCode . Code != Code . Ldloc_S )
295+ throw new InvalidOperationException ( ) ;
296+ if ( inst . Next . OpCode . Code != Code . Brfalse )
297+ throw new InvalidOperationException ( ) ;
298+
299+ var baseInst = inst . Next . Next ;
300+
301+ il . InsertBefore ( baseInst , il . Create ( OpCodes . Ldloc_S , ( VariableDefinition ) inst . Previous . Operand ) ) ;
302+ il . InsertBefore ( baseInst , il . Create ( OpCodes . Callvirt , symbolGetAttributes ) ) ;
303+ il . InsertBefore ( baseInst , il . Create ( OpCodes . Stloc , il . Body . Variables [ attributeArrayLocalIndex ] ) ) ;
304+ il . InsertBefore ( baseInst , il . Create ( OpCodes . Ldloca_S , il . Body . Variables [ attributeArrayLocalIndex ] ) ) ;
305+ il . InsertBefore ( baseInst , il . Create ( OpCodes . Call , symbolIsEmpty ) ) ;
306+ il . InsertBefore ( baseInst , il . Create ( OpCodes . Brfalse , ( Instruction ) inst . Next . Operand ) ) ;
307+ break ;
308+ }
309+ }
310+ }
240311 }
241312}
0 commit comments