[Build] Renewal GenDummy (#583)
[platform/core/csapi/tizenfx.git] / tools / src / GenDummy / Converter.cs
1 /*
2  * Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 using System;
18 using System.Linq;
19 using System.Reflection;
20 using Mono.Cecil;
21 using Mono.Cecil.Cil;
22
23 namespace GenDummy
24 {
25     public class Converter
26     {
27         private AssemblyDefinition _asm;
28
29         public Converter(string srcAssemblyPath)
30         {
31             _asm = AssemblyDefinition.ReadAssembly(srcAssemblyPath);
32         }
33
34         public void ConvertTo(string targetAssemblyPath)
35         {
36             VisitAssembly(_asm);
37             _asm.Write(targetAssemblyPath);
38         }
39
40         private void VisitAssembly(AssemblyDefinition assembly)
41         {
42             Log.Verbose("Assembly: " + assembly.FullName);
43
44             var attr = assembly.CustomAttributes.FirstOrDefault(a => a.AttributeType.FullName == "System.Runtime.CompilerServices.ReferenceAssemblyAttribute");
45             if (attr != null) {
46                 assembly.CustomAttributes.Remove(attr);
47             }
48
49             foreach (var module in assembly.Modules)
50             {
51                 VisitModule(module);
52             }
53         }
54
55         private void VisitModule(ModuleDefinition module)
56         {
57             Log.Verbose("Module: " + module.Name);
58             foreach (var type in module.Types)
59             {
60                 VisitType(type);
61             }
62         }
63
64         private void VisitType(TypeDefinition type)
65         {
66             Log.Verbose("Type: " + type.FullName);
67
68             foreach (var prop in type.Properties)
69             {
70                 VisitProperty(prop);
71             }
72
73             foreach (var method in type.Methods)
74             {
75                 VisitMethod(method);
76             }
77
78             foreach (var ev in type.Events)
79             {
80                 VisitEvent(ev);
81             }
82
83             foreach (var nested in type.NestedTypes)
84             {
85                 VisitType(nested);
86             }
87         }
88
89         private void VisitProperty(PropertyDefinition prop)
90         {
91             Log.Verbose("  Property: " + prop.FullName);
92             if (prop.GetMethod != null)
93             {
94                 Log.Verbose("    Getter:");
95                 ReplaceWithThrowPNSE(prop.GetMethod);
96             }
97             if (prop.SetMethod != null)
98             {
99                 Log.Verbose("    Setter:");
100                 ReplaceWithThrowPNSE(prop.SetMethod);
101             }
102         }
103
104         private void VisitMethod(MethodDefinition method)
105         {
106             Log.Verbose($"  Method: {method.FullName}");
107             if (method.Name == "Finalize")
108             {
109                 ReplaceWithVoidReturn(method);
110             }
111             else
112             {
113                 ReplaceWithThrowPNSE(method);
114             }
115         }
116
117         private void VisitEvent(EventDefinition ev)
118         {
119             Log.Verbose("  Event: " + ev.FullName);
120             if (ev.AddMethod != null)
121             {
122                 Log.Verbose("    Add:");
123                 ReplaceWithThrowPNSE(ev.AddMethod);
124             }
125             if (ev.RemoveMethod != null)
126             {
127                 Log.Verbose("    Remove:");
128                 ReplaceWithThrowPNSE(ev.RemoveMethod);
129             }
130             foreach (var method in ev.OtherMethods)
131             {
132                 Log.Verbose("    Other: " + method.FullName);
133                 ReplaceWithThrowPNSE(method);
134             }
135         }
136
137         private bool ReplaceWithThrowPNSE(MethodDefinition method)
138         {
139             if (method.HasBody && method.IsIL)
140             {
141                 ClearMethodBody(method);
142
143                 ConstructorInfo exceptionCtor = typeof(PlatformNotSupportedException).GetConstructor(new Type[] { typeof(System.String) });
144                 var exceptionCtorRef = method.Module.ImportReference(exceptionCtor);
145
146                 var processor = method.Body.GetILProcessor();
147                 processor.Append(processor.Create(OpCodes.Ldstr, "Not Supported Feature"));
148                 processor.Append(processor.Create(OpCodes.Newobj, exceptionCtorRef));
149                 processor.Append(processor.Create(OpCodes.Throw));
150
151                 PrintMethodBody(method);
152
153                 return true;
154             }
155             return false;
156         }
157
158         private bool ReplaceWithVoidReturn(MethodDefinition method)
159         {
160             if (method.HasBody && method.IsIL)
161             {
162                 ClearMethodBody(method);
163
164                 var processor = method.Body.GetILProcessor();
165                 processor.Append(processor.Create(OpCodes.Nop));
166                 processor.Append(processor.Create(OpCodes.Ret));
167
168                 PrintMethodBody(method);
169
170                 return true;
171             }
172             return false;
173         }
174
175         private void ClearMethodBody(MethodDefinition method)
176         {
177             var processor = method.Body.GetILProcessor();
178             while (method.Body.Instructions.Count > 0)
179             {
180                 processor.Remove(method.Body.Instructions[0]);
181             }
182         }
183
184         private void PrintMethodBody(MethodDefinition method)
185         {
186             if (method.HasBody)
187             {
188                 var iLProcessor = method.Body.GetILProcessor();
189                 foreach (var inst in method.Body.Instructions)
190                 {
191                     Log.Verbose($"      {inst.ToString()}");
192                 }
193             }
194         }
195     }
196
197 }