Skip to content

Commit 9486156

Browse files
committed
Disable CS0649 when a field has attributes. #6
1 parent 59b923b commit 9486156

File tree

4 files changed

+175
-4
lines changed

4 files changed

+175
-4
lines changed

core/RoslynCompilerFix/CSharpCompilerFix.cs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
// Exceprt from Mono.Cecil.Tests
2+
3+
// Author:
4+
// Jb Evain ([email protected])
5+
//
6+
// Copyright (c) 2008 - 2015 Jb Evain
7+
// Copyright (c) 2008 - 2011 Novell, Inc.
8+
//
9+
// Licensed under the MIT/X11 license.
10+
11+
using System;
12+
using System.Linq;
13+
using SR = System.Reflection;
14+
15+
namespace Mono.Cecil
16+
{
17+
public static class Extensions
18+
{
19+
public static MethodDefinition GetMethod(this TypeDefinition self, string name)
20+
{
21+
return self.Methods.Where(m => m.Name == name).First();
22+
}
23+
24+
public static FieldDefinition GetField(this TypeDefinition self, string name)
25+
{
26+
return self.Fields.Where(f => f.Name == name).First();
27+
}
28+
29+
public static TypeDefinition ToDefinition(this Type self)
30+
{
31+
var module = ModuleDefinition.ReadModule(self.Module.FullyQualifiedName);
32+
return (TypeDefinition)module.LookupToken(self.MetadataToken);
33+
}
34+
35+
public static MethodDefinition ToDefinition(this SR.MethodBase method)
36+
{
37+
var declaring_type = method.DeclaringType.ToDefinition();
38+
return (MethodDefinition)declaring_type.Module.LookupToken(method.MetadataToken);
39+
}
40+
41+
public static FieldDefinition ToDefinition(this SR.FieldInfo field)
42+
{
43+
var declaring_type = field.DeclaringType.ToDefinition();
44+
return (FieldDefinition)declaring_type.Module.LookupToken(field.MetadataToken);
45+
}
46+
47+
public static TypeReference MakeGenericType(this TypeReference self, params TypeReference[] arguments)
48+
{
49+
if (self.GenericParameters.Count != arguments.Length)
50+
throw new ArgumentException();
51+
52+
var instance = new GenericInstanceType(self);
53+
foreach (var argument in arguments)
54+
instance.GenericArguments.Add(argument);
55+
56+
return instance;
57+
}
58+
59+
public static MethodReference MakeGenericMethod(this MethodReference self, params TypeReference[] arguments)
60+
{
61+
if (self.GenericParameters.Count != arguments.Length)
62+
throw new ArgumentException();
63+
64+
var instance = new GenericInstanceMethod(self);
65+
foreach (var argument in arguments)
66+
instance.GenericArguments.Add(argument);
67+
68+
return instance;
69+
}
70+
71+
public static MethodReference MakeGeneric(this MethodReference self, params TypeReference[] arguments)
72+
{
73+
var reference = new MethodReference(self.Name, self.ReturnType, self.DeclaringType.MakeGenericType(arguments))
74+
{
75+
HasThis = self.HasThis,
76+
ExplicitThis = self.ExplicitThis,
77+
CallingConvention = self.CallingConvention,
78+
};
79+
80+
foreach (var parameter in self.Parameters)
81+
reference.Parameters.Add(new ParameterDefinition(parameter.ParameterType));
82+
83+
foreach (var generic_parameter in self.GenericParameters)
84+
reference.GenericParameters.Add(new GenericParameter(generic_parameter.Name, reference));
85+
86+
return reference;
87+
}
88+
89+
public static FieldReference MakeGeneric(this FieldReference self, params TypeReference[] arguments)
90+
{
91+
return new FieldReference(self.Name, self.FieldType, self.DeclaringType.MakeGenericType(arguments));
92+
}
93+
}
94+
}

core/RoslynCompilerFix/RoslynCompilerFix.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
<Reference Include="System.Xml" />
6161
</ItemGroup>
6262
<ItemGroup>
63+
<Compile Include="CecilExtensions.cs" />
6364
<Compile Include="CSharpCompilerFix.cs" />
6465
<Compile Include="Program.cs" />
6566
<Compile Include="Properties\AssemblyInfo.cs" />

samples/Basic/Assets/Scripts/Test04.cs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,18 @@ public class Test04 : MonoBehaviour
55
{
66
// warning test
77

8-
private Hashtable table; // CS0649
8+
[SerializeField]
9+
private Hashtable tableSerialized; // CS0649
10+
private Hashtable tableAssigned; // CS0649
911

10-
private int x = 1; // CS0414
12+
[SerializeField]
13+
private int xSerialized = 1; // CS0414
14+
private int xAssigned = 1; // CS0414
1115

1216
public void Func(object o, string p)
1317
{
14-
int j; // CS0168
15-
table[p] = o;
18+
int j; // CS0168
19+
tableSerialized[p] = o;
20+
tableAssigned[p] = o;
1621
}
1722
}

0 commit comments

Comments
 (0)