File: CompilerHelper.vb

package info (click to toggle)
mono-basic 2.6.2-2
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 18,852 kB
  • ctags: 809
  • sloc: cs: 8,852; makefile: 516; sh: 307
file content (216 lines) | stat: -rw-r--r-- 8,626 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
' 
' Visual Basic.Net COmpiler
' Copyright (C) 2004 - 2006 Rolf Bjarne Kvinge, rbjarnek at users.sourceforge.net
' 
' This library is free software; you can redistribute it and/or
' modify it under the terms of the GNU Lesser General Public
' License as published by the Free Software Foundation; either
' version 2.1 of the License, or (at your option) any later version.
' 
' This library is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY; without even the implied warranty of
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
' Lesser General Public License for more details.
' 
' You should have received a copy of the GNU Lesser General Public
' License along with this library; if not, write to the Free Software
' Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
' 

Option Strict On
Option Explicit On

Imports System.Reflection

<Serializable()> _
Friend Class CompilerHelper
    Inherits MarshalByRefObject
    Implements IDisposable

    Private m_Compiler As Object
    Private m_ConsoleOutput As String
    Private m_ConsoleStream As IO.StringWriter

    Private m_Parent As TestList

    Private m_CompilerPath As String
    Private m_CompilerOriginalPath As String
    Private m_CompilerMethod As MethodInfo

    ''' <summary>
    ''' If the current helper is loaded into the default domain, 
    ''' then this field is loaded into the other domain and everything
    ''' is forwarded into this helper.
    ''' </summary>
    ''' <remarks></remarks>
    Private m_CompilerHelper As CompilerHelper
    Private m_CompilerDomain As AppDomain

    Private WithEvents m_CompilerWatcher As New IO.FileSystemWatcher

    Private m_Dirty As Boolean = True


    Public Overrides Function InitializeLifetimeService() As Object
        Dim lease As Runtime.Remoting.Lifetime.ILease
        lease = CType(MyBase.InitializeLifetimeService, Runtime.Remoting.Lifetime.ILease)
        lease.InitialLeaseTime = TimeSpan.Zero
        Return lease
    End Function


    Property ConsoleOutput() As String
        Get
            If m_CompilerHelper IsNot Nothing Then
                Try
                    Return m_CompilerHelper.ConsoleOutput
                Catch ex As Runtime.Remoting.RemotingException
                    Return ex.Message
                End Try
            Else
                Return m_ConsoleOutput
            End If
        End Get
        Private Set(ByVal value As String)
            m_ConsoleOutput = value
        End Set
    End Property
    Private Sub m_CompilerWatcher_Changed(ByVal sender As Object, ByVal e As System.IO.FileSystemEventArgs) Handles m_CompilerWatcher.Changed
        m_Dirty = True
    End Sub

    Private Sub m_CompilerWatcher_Created(ByVal sender As Object, ByVal e As System.IO.FileSystemEventArgs) Handles m_CompilerWatcher.Created
        m_Dirty = True
    End Sub

    ReadOnly Property CompilerPath() As String
        Get
            If m_CompilerPath Is Nothing Then
                Return m_CompilerOriginalPath
            Else
                Return m_CompilerPath
            End If
        End Get
    End Property

    Sub ReloadCompiler()
        m_ConsoleStream = New IO.StringWriter
        Console.SetOut(m_ConsoleStream)
        m_Compiler = Activator.CreateInstance("vbnc", "vbnc.Compiler").Unwrap ' m_CompilerType)
        m_CompilerMethod = m_Compiler.GetType.GetMethod("Compile", New Type() {GetType(String())})
        Dim responsefilename As String = IO.Path.GetFullPath("..\..\vbnc\bin\vbnc.rsp")
        Dim responsefilename2 As String = IO.Path.Combine(IO.Path.GetDirectoryName(m_Compiler.GetType.Assembly.Location), "vbnc.rsp")
        If IO.File.Exists(responsefilename2) = False Then
            IO.File.Copy(responsefilename, responsefilename2)
        End If
    End Sub

    Private Sub SetupDomain()
        If m_CompilerDomain IsNot Nothing Then
            AppDomain.Unload(m_CompilerDomain)
            m_CompilerDomain = Nothing
        End If

        Dim ns As New AppDomainSetup
        ns.ShadowCopyFiles = "true"
        ns.ShadowCopyDirectories = IO.Path.GetFullPath("..\..\vbnc\bin")
        ns.CachePath = IO.Path.GetFullPath("tmpcompiler")
        ns.PrivateBinPath = "rt\bin;vbnc\bin"
        ns.ApplicationBase = IO.Path.GetDirectoryName(IO.Path.GetDirectoryName(IO.Path.GetDirectoryName(Reflection.Assembly.GetExecutingAssembly.Location)))
        Static counter As Integer
        counter += 1
        m_CompilerDomain = AppDomain.CreateDomain("Compiler #" & counter.ToString, Nothing, ns)
        Debug.WriteLine("Created domain: " & m_CompilerDomain.FriendlyName)
        Debug.WriteLine("Created domain: " & m_CompilerDomain.FriendlyName)
        Debug.WriteLine("Created domain: " & m_CompilerDomain.FriendlyName)
        Debug.WriteLine("Created domain: " & m_CompilerDomain.FriendlyName)
        Debug.WriteLine("Created domain: " & m_CompilerDomain.FriendlyName)
        Debug.WriteLine("Created domain: " & m_CompilerDomain.FriendlyName)
        Debug.WriteLine("Created domain: " & m_CompilerDomain.FriendlyName)
        m_Dirty = False
    End Sub

    Private Sub CreateCompilerHelper()
        If m_CompilerHelper IsNot Nothing Then
            m_CompilerHelper.Dispose()
            m_CompilerHelper = Nothing
        End If
        SetupDomain()
        'm_CompilerHelper = CType(Activator.CreateInstance(m_CompilerDomain, "rt", GetType(CompilerHelper).FullName, True, BindingFlags.Default, Nothing, New Object() {m_Parent, m_CompilerOriginalPath}, Nothing, Nothing, Nothing).Unwrap, CompilerHelper)
    End Sub

    Sub New(ByVal Tests As TestList, ByVal CompilerPath As String)
        Try
            m_Parent = Tests
            m_CompilerOriginalPath = CompilerPath

            If AppDomain.CurrentDomain.IsDefaultAppDomain Then
                m_CompilerWatcher.NotifyFilter = IO.NotifyFilters.CreationTime Or IO.NotifyFilters.FileName Or IO.NotifyFilters.LastWrite
                m_CompilerWatcher.SynchronizingObject = MainModule.frmMain
                m_CompilerWatcher.Path = IO.Path.GetDirectoryName(m_CompilerOriginalPath)
                m_CompilerWatcher.Filter = IO.Path.GetFileName(m_CompilerOriginalPath)
                m_CompilerWatcher.EnableRaisingEvents = True
            End If
        Catch ex As Exception
            Throw
        End Try
    End Sub

    Function Compile(ByVal Args() As String) As Boolean
        Dim result As Boolean

        Try
            If AppDomain.CurrentDomain.IsDefaultAppDomain Then
                If m_Dirty Then CreateCompilerHelper()
                Debug.Assert(m_CompilerHelper IsNot Nothing)
                Return m_CompilerHelper.Compile(Args)
            Else
                ReloadCompiler()
                result = CBool(m_CompilerMethod.Invoke(m_Compiler, New Object() {Args}))
                ConsoleOutput = m_ConsoleStream.ToString

                Debug.WriteLine("Done test in Domain: " & AppDomain.CurrentDomain.FriendlyName & " with executable: " & m_Compiler.GetType.Assembly.Location)
            End If
        Catch ex As Runtime.Remoting.RemotingException
            result = False
            m_ConsoleStream = New IO.StringWriter()
            m_ConsoleStream.WriteLine("Exception while executing test: " & ex.Message)
        Catch ex As Exception
            result = False
            m_ConsoleStream.WriteLine("Exception while executing test: " & ex.Message)
        End Try

        Return result
    End Function

    Private disposedValue As Boolean = False        ' To detect redundant calls

    ' IDisposable
    Protected Overridable Sub Dispose(ByVal disposing As Boolean)
        If Not Me.disposedValue Then
            If disposing Then
                ' TODO: free unmanaged resources when explicitly called
            End If
            If m_CompilerHelper IsNot Nothing Then
                m_CompilerHelper.Dispose()
                m_CompilerHelper = Nothing
            End If
            If m_CompilerDomain IsNot Nothing Then
                AppDomain.Unload(m_CompilerDomain)
                m_CompilerDomain = Nothing
            End If
            ' TODO: free shared unmanaged resources
        End If
        Me.disposedValue = True
    End Sub

#Region " IDisposable Support "
    ' This code added by Visual Basic to correctly implement the disposable pattern.
    Public Sub Dispose() Implements IDisposable.Dispose
        ' Do not change this code.  Put cleanup code in Dispose(ByVal disposing As Boolean) above.
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
#End Region

End Class