1 #Region "Microsoft.VisualBasic::c2937ea1bd2676f027c9d5dc75002b6c, Microsoft.VisualBasic.Core\Extensions\CodeDOM\CodeDOM.vb"
2
3     ' Author:
4     
5     '       asuka (amethyst.asuka@gcmodeller.org)
6     '       xie (genetics@smrucc.org)
7     '       xieguigang (xie.guigang@live.com)
8     
9     ' Copyright (c) 2018 GPL3 Licensed
10     
11     
12     ' GNU GENERAL PUBLIC LICENSE (GPL3)
13     
14     
15     ' This program is free software: you can redistribute it and/or modify
16     ' it under the terms of the GNU General Public License as published by
17     ' the Free Software Foundation, either version 3 of the License, or
18     ' (at your option) any later version.
19     
20     ' This program is distributed in the hope that it will be useful,
21     ' but WITHOUT ANY WARRANTY; without even the implied warranty of
22     ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23     ' GNU General Public License for more details.
24     
25     ' You should have received a copy of the GNU General Public License
26     ' along with this program. If not, see <http://www.gnu.org/licenses/>.
27
28
29
30     ' /********************************************************************************/
31
32     ' Summaries:
33
34     '     Module CodeDOMExtension
35     
36     '         Properties: DllProfile, DotNETFramework, ExecutableProfile
37     
38     '         Function: (+4 Overloads) Compile, CompileDll, CompileExe, GenerateCode, GetDebugInformation
39     '                   Icon, ImportsNamespace
40     
41     
42     ' /********************************************************************************/
43
44 #End Region
45
46 Imports System.CodeDom
47 Imports System.CodeDom.Compiler
48 Imports System.Collections.Specialized
49 Imports System.IO
50 Imports System.Reflection
51 Imports System.Runtime.CompilerServices
52 Imports System.Text
53 Imports Microsoft.VisualBasic.Language
54 Imports Microsoft.VisualBasic.Linq
55
56 Namespace Emit.CodeDOM_VBC
57
58     <Extension> Public Module CodeDOMExtension
59
60         ''' <summary>
61         ''' ```
62         ''' C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6\
63         ''' ```
64         ''' </summary>
65         Public Const net46Default As String = "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6\"
66
67         ''' <summary>
68         ''' 设置所编译的应用程序的图标
69         ''' </summary>
70         ''' <param name="iconPath"></param>
71         ''' <returns></returns>
72         Public Function Icon(iconPath As StringAs String
73             Return $"/target:winexe /win32icon:""{iconPath}"""
74         End Function
75
76         <Extension> Public Function ImportsNamespace(refList As IEnumerable(Of String)) As CodeDom.CodeNamespaceImport()
77             Dim nsArray As New List(Of CodeNamespaceImport) From {
78                 New CodeDom.CodeNamespaceImport("Microsoft.VisualBasic"),
79                 New CodeDom.CodeNamespaceImport("System"),
80                 New CodeDom.CodeNamespaceImport("System.Collections"),
81                 New CodeDom.CodeNamespaceImport("System.Collections.Generic"),
82                 New CodeDom.CodeNamespaceImport("System.Data"),
83                 New CodeDom.CodeNamespaceImport("System.Diagnostics"),
84                 New CodeDom.CodeNamespaceImport("System.Linq"),
85                 New CodeDom.CodeNamespaceImport("System.Xml.Linq"),
86                 New CodeDom.CodeNamespaceImport("System.Text.RegularExpressions")
87             }
88             Call nsArray.Add(refList.Select(Function(ns) New CodeNamespaceImport(ns)).ToArray)
89             Return nsArray.ToArray
90         End Function
91
92         ''' <summary>
93         ''' Generate the source code from the CodeDOM object model.(根据对象模型生成源代码以方便调试程序)
94         ''' </summary>
95         ''' <param name="NameSpace"></param>
96         ''' <param name="CodeStyle">VisualBasic, C#</param>
97         ''' <returns></returns>
98         ''' <remarks>
99         ''' You can easily convert the source code between VisualBasic and C# using this function just by makes change in statement: 
100         ''' CodeDomProvider.GetCompilerInfo("VisualBasic").CreateProvider().GenerateCodeFromNamespace([NameSpace], sWriter, Options)
101         ''' Modify the VisualBasic in to C#
102         ''' </remarks>
103         <Extension> Public Function GenerateCode([NameSpace] As CodeNamespace, Optional CodeStyle As String = "VisualBasic"As String
104             Dim code As New StringBuilder()
105
106             Using sWriter As New StringWriter(code)
107                 Dim OptionAs New CodeGeneratorOptions() With {
108                     .IndentString = "  ",
109                     .ElseOnClosing = True,
110                     .BlankLinesBetweenMembers = True
111                 }
112                 CodeDomProvider.GetCompilerInfo(CodeStyle) _
113                     .CreateProvider() _
114                     .GenerateCodeFromNamespace([NameSpace], sWriter, Options)
115
116                 Return code.ToString()
117             End Using
118         End Function
119
120         ''' <summary>
121         ''' Compile the codedom object model into a binary assembly module file.(将CodeDOM对象模型编译为二进制应用程序文件)
122         ''' </summary>
123         ''' <param name="ObjectModel">CodeDom dynamic code object model.(目标动态代码的对象模型)</param>
124         ''' <param name="Reference">Reference assemby file path collection.(用户代码的引用DLL文件列表)</param>
125         ''' <param name="DotNETReferenceAssembliesDir">.NET Framework SDK</param>
126         ''' <param name="CodeStyle">VisualBasic, C#</param>
127         ''' <returns></returns>
128         ''' <remarks></remarks>
129         <Extension> Public Function Compile(ObjectModel As CodeNamespace,
130                                             Reference As String(),
131                                             DotNETReferenceAssembliesDir As String,
132                                             Optional CodeStyle As String = "VisualBasic"As Assembly
133             Dim assembly As New CodeCompileUnit
134             Call assembly.Namespaces.Add(ObjectModel)
135             Return Compile(assembly, Reference, DotNETReferenceAssembliesDir, CodeStyle)
136         End Function
137
138         ''' <summary>
139         ''' Compile the codedom object model into a binary assembly module file.(将CodeDOM对象模型编译为二进制应用程序文件)
140         ''' </summary>
141         ''' <param name="ObjectModel">CodeDom dynamic code object model.(目标动态代码的对象模型)</param>
142         ''' <param name="Reference">Reference assemby file path collection.(用户代码的引用DLL文件列表)</param>
143         ''' <param name="DotNETReferenceAssembliesDir">.NET Framework SDK</param>
144         ''' <param name="CodeStyle">VisualBasic, C#</param>
145         ''' <returns></returns>
146         ''' <remarks></remarks>
147         <Extension> Public Function Compile(ObjectModel As CodeNamespace,
148                                             Reference As String(),
149                                             DotNETReferenceAssembliesDir As String,
150                                             OptionAs CompilerParameters,
151                                             Optional CodeStyle As String = "VisualBasic"As Assembly
152             With New CodeCompileUnit
153                 Call .Namespaces.Add(ObjectModel)
154                 Return .Compile(Reference, DotNETReferenceAssembliesDir, Options, CodeStyle)
155             End With
156         End Function
157
158         ''' <summary>
159         ''' Compile the codedom object model into a binary assembly module file.(将CodeDOM对象模型编译为二进制应用程序文件)
160         ''' </summary>
161         ''' <param name="ObjectModel">CodeDom dynamic code object model.(目标动态代码的对象模型)</param>
162         ''' <param name="Reference">Reference assemby file path collection.(用户代码的引用DLL文件列表)</param>
163         ''' <param name="DotNETReferenceAssembliesDir">.NET Framework SDK</param>
164         ''' <param name="CodeStyle">VisualBasic, C#</param>
165         ''' <returns></returns>
166         ''' <remarks></remarks>
167         <Extension> Public Function Compile(ObjectModel As CodeCompileUnit,
168                                             Reference As String(),
169                                             DotNETReferenceAssembliesDir As String,
170                                             Optional CodeStyle As String = "VisualBasic"As Assembly
171
172             Dim OptionAs New CompilerParameters With {
173                 .GenerateInMemory = True,
174                 .IncludeDebugInformation = False,
175                 .GenerateExecutable = False
176             }
177             Return Compile(ObjectModel, Reference, DotNETReferenceAssembliesDir, Options, CodeStyle)
178         End Function
179
180         ''' <summary>
181         ''' .exe的编译配置文件
182         ''' </summary>
183         ''' <returns></returns>
184         Public ReadOnly Property ExecutableProfile As CompilerParameters
185             Get
186                 Dim OptionAs New CompilerParameters
187                 Options.GenerateInMemory = False
188                 Options.IncludeDebugInformation = True
189                 Options.GenerateExecutable = True
190
191                 Return Options
192             End Get
193         End Property
194
195         ''' <summary>
196         ''' .Dll的编译配置文件
197         ''' </summary>
198         ''' <returns></returns>
199         Public ReadOnly Property DllProfile As CompilerParameters
200             Get
201                 Dim OptionAs New CompilerParameters
202                 Options.GenerateInMemory = False
203                 Options.IncludeDebugInformation = True
204                 Options.GenerateExecutable = False
205
206                 Return Options
207             End Get
208         End Property
209
210         <MethodImpl(MethodImplOptions.AggressiveInlining)>
211         Public Function CompileExe(assm As CodeCompileUnit, ref As String(), SDK As StringOptional codeStyle As String = "VisualBasic"As Assembly
212             Return Compile(assm, ref, SDK, ExecutableProfile, codeStyle)
213         End Function
214
215         <MethodImpl(MethodImplOptions.AggressiveInlining)>
216         <Extension>
217         Public Function CompileDll(assm As CodeCompileUnit,
218                                    ref As IEnumerable(Of String),
219                                    SDK As String,
220                                    Optional codeStyle As String = "VisualBasic"As Assembly
221             Return Compile(assm, ref.ToArray, SDK, DllProfile, codeStyle)
222         End Function
223
224         ''' <summary>
225         ''' Compile the codedom object model into a binary assembly module file.(将CodeDOM对象模型编译为二进制应用程序文件)
226         ''' </summary>
227         ''' <param name="ObjectModel">CodeDom dynamic code object model.(目标动态代码的对象模型)</param>
228         ''' <param name="Reference">Reference assemby file path collection.(用户代码的引用DLL文件列表)</param>
229         ''' <param name="DotNETReferenceAssembliesDir">.NET Framework SDK</param>
230         ''' <param name="CodeStyle">VisualBasic, C#</param>
231         ''' <returns></returns>
232         ''' <remarks></remarks>
233         <Extension> Public Function Compile(ObjectModel As CodeCompileUnit,
234                                             Reference As String(),
235                                             DotNETReferenceAssembliesDir As String,
236                                             OptionAs CompilerParameters,
237                                             Optional CodeStyle As String = "VisualBasic"As Assembly
238
239             Dim CodeDomProvider As CodeDomProvider = CodeDomProvider.CreateProvider(CodeStyle)
240             Dim refs As StringCollection = Options.ReferencedAssemblies
241
242             If Not Reference.IsNullOrEmpty Then
243                 With From path As String
244                      In Reference
245                      Where Array.IndexOf(DotNETFramework, BaseName(path)) = -1
246                      Select path
247
248                     Call refs.AddRange(.ByRef.ToArray)
249                 End With
250             End If
251
252             Call refs.AddRange({
253                 DotNETReferenceAssembliesDir & "\System.dll",
254                 DotNETReferenceAssembliesDir & "\System.Core.dll",
255                 DotNETReferenceAssembliesDir & "\System.Data.dll",
256                 DotNETReferenceAssembliesDir & "\System.Data.DataSetExtensions.dll",
257                 DotNETReferenceAssembliesDir & "\System.Xml.dll",
258                 DotNETReferenceAssembliesDir & "\System.Xml.Linq.dll"
259             })
260
261             Dim Compiled = CodeDomProvider.CompileAssemblyFromDom(Options, ObjectModel)
262
263             Call GetDebugInformation(Compiled, ObjectModel).__DEBUG_ECHO
264
265             Return Compiled.CompiledAssembly
266         End Function
267
268         ''' <summary>
269         ''' 基本的引用集合
270         ''' </summary>
271         ''' <returns></returns>
272         Public ReadOnly Property DotNETFramework As String() = {
273             "System",
274             "System.Core",
275             "System.Data",
276             "System.Data.DataSetExtensions",
277             "System.Xml",
278             "System.Xml.Linq"
279         }
280
281         ''' <summary>
282         ''' Output logs
283         ''' </summary>
284         ''' <param name="CompiledResult"></param>
285         ''' <param name="Assembly"></param>
286         ''' <returns></returns>
287         <Extension> Public Function GetDebugInformation(CompiledResult As CompilerResults, Assembly As CodeCompileUnit) As String
288             With New StringBuilder
289                 Call .AppendLine(GenerateCode(Assembly.Namespaces.Item(0)) & vbCrLf)
290
291                 Call .AppendLine("Error Information: ")
292
293                 For Each [Error] In CompiledResult.Errors
294                     .AppendLine([Error].ToString)
295                 Next
296
297                 Call .AppendLine(vbCrLf & "Compiler Output:")
298                 For Each Line As String In CompiledResult.Output
299                     .AppendLine(Line)
300                 Next
301
302                 Call .ToString.SaveTo(".\CodeDom.log")
303                 Return .ToString
304             End With
305         End Function
306     End Module
307 End Namespace