[MonoDevelop] BooBinding patch bug 324223
Manuel de la Pena
mandel at themacaque.com
Tue Mar 17 13:40:05 EDT 2009
Hello there,
Here is the patch I have been working on to shell the Boo compilation
allowing to recompile without having problems because the compilation
loaded assemblies to the AppDomain
(https://bugzilla.novell.com/show_bug.cgi?id=324223)
I hope it helps.
Kr,
manuel => mandel
PS: Thanks to Tak and mhutch at IRC... I must have been a pain in the
ass, in my defense is my first monodevelop patch :P
-------------- next part --------------
Index: BooBindingCompilerServices.boo
===================================================================
--- BooBindingCompilerServices.boo (revision 129338)
+++ BooBindingCompilerServices.boo (working copy)
@@ -20,19 +20,15 @@
namespace BooBinding
import System
-import System.Diagnostics
import System.IO
import System.CodeDom.Compiler
import System.Text
-import System.Reflection
+import System.Text.RegularExpressions
-import MonoDevelop.Core.Gui.Components
import MonoDevelop.Core
+import MonoDevelop.Core.ProgressMonitoring
import MonoDevelop.Projects
-import Boo.Lang.Compiler
-import Boo.Lang.Compiler.Resources
-
[extension] #FIXME: workaround BOO-1167
def GetAllReferences (this as ProjectItemCollection) as ProjectReference*:
for item in this:
@@ -45,6 +41,14 @@
public class BooBindingCompilerServices:
+
+ #region Private variables
+
+ #we use a static string builder to be able to read the ouput from the compiler process
+ private static _output as StringBuilder = StringBuilder()
+
+ #endregion
+
public def CanCompile (fileName as string):
return Path.GetExtension(fileName).ToUpper() == ".BOO"
@@ -52,77 +56,111 @@
compilerparameters = cast(BooCompilerParameters, configuration.CompilationParameters)
if compilerparameters is null:
compilerparameters = BooCompilerParameters()
+ #we get the compiler target to be used
+ compilerTarget as string = "exe"
- // FIXME: Use outdir 'configuration.OutputDirectory'
- compiler = Boo.Lang.Compiler.BooCompiler()
- compiler.Parameters.Pipeline = Pipelines.CompileToFile()
-
- compiler.Parameters.Debug = configuration.DebugMode
- compiler.Parameters.OutputAssembly = configuration.CompiledOutputName
- compiler.Parameters.Ducky = compilerparameters.Ducky
-
- # Make sure we don't load the generated assembly at all
- compiler.Parameters.GenerateInMemory = false
-
+ if configuration.CompileTarget == CompileTarget.Exe:
+ compilerTarget = "exe"
+ elif configuration.CompileTarget == CompileTarget.Library:
+ compilerTarget = "library"
+ elif configuration.CompileTarget == CompileTarget.WinExe:
+ compilerTarget = "winexe"
+
+ parameters as StringBuilder = StringBuilder(
+ "-o:${configuration.CompiledOutputName} -t:${compilerTarget}")
+
+ #we decide if we want to use ducks
+ if compilerparameters.Ducky:
+ parameters.Append(" -ducky ")
+
+ #we decide if we are going to define the debug var
+ if configuration.DebugMode:
+ parameters.Append(" -define:DEBUG ")
+
+ #we add the different references
for lib as ProjectReference in projectItems.GetAllReferences ():
for fileName as string in lib.GetReferencedFileNames (configuration.Id):
- compiler.Parameters.References.Add(Assembly.LoadFile(fileName))
-
+ parameters.Append(" -reference:${fileName} ")
+
for finfo as ProjectFile in projectItems.GetAllFiles ():
if finfo.Subtype != Subtype.Directory:
if finfo.BuildAction == BuildAction.Compile:
- compiler.Parameters.Input.Add(Boo.Lang.Compiler.IO.FileInput(finfo.Name))
+ parameters.Append(" ${finfo.FilePath} ")
elif finfo.BuildAction == BuildAction.EmbeddedResource:
- compiler.Parameters.Resources.Add (EmbeddedFileResource (finfo.Name))
+ parameters.Append(" -resource:${finfo.FilePath}")
+ tf = TempFileCollection ()
+ compilationOutput = DoCompilation (monitor, parameters.ToString(), configuration.OutputDirectory )
+ monitor.Log.WriteLine(GettextCatalog.GetString("Parsing output"))
+ return ParseOutput (tf, compilationOutput)
- if configuration.CompileTarget == CompileTarget.Exe:
- compiler.Parameters.OutputType = CompilerOutputType.ConsoleApplication
- elif configuration.CompileTarget == CompileTarget.Library:
- compiler.Parameters.OutputType = CompilerOutputType.Library
- elif configuration.CompileTarget == CompileTarget.WinExe:
- compiler.Parameters.OutputType = CompilerOutputType.WindowsApplication
- tf = TempFileCollection ()
- context = DoCompilation (monitor, compiler)
- cr = ParseOutput (tf, context)
- return cr
-
- private def DoCompilation (monitor as IProgressMonitor, compiler as Boo.Lang.Compiler.BooCompiler):
+ private def DoCompilation (monitor as IProgressMonitor, parameters as string, outpurDir as string):
try:
- monitor.BeginTask (null, 2)
- monitor.Log.WriteLine ("Compiling Boo source code ...")
- context = compiler.Run()
- monitor.Step (1)
- return context
+
+ swError = StringWriter ()
+ chainedError as LogTextWriter = LogTextWriter()
+ chainedError.ChainWriter(monitor.Log)
+ chainedError.ChainWriter(swError);
+
+ operationMonitor = AggregatedOperationMonitor(monitor)
+ monitor.Log.WriteLine(GettextCatalog.GetString("Starting Boo compilation"))
+ monitor.Log.WriteLine(GettextCatalog.GetString("booc ${parameters}"))
+
+ #we need to redirect the error output to the stdout to make sure we can use it correctly
+ System.Console.SetError(swError)
+
+ #we create a new process that will be used to execute the command line of the compiler
+ wrapper = MonoDevelop.Core.Runtime.ProcessService.StartProcess("booc",parameters ,
+ Path.GetDirectoryName(outpurDir),monitor.Log, chainedError, null)
+
+ #we take care of cancelation
+ operationMonitor.AddOperation(wrapper);
+ wrapper.WaitForOutput();
+ exitCode = wrapper.ExitCode
+
+ if monitor.IsCancelRequested:
+ monitor.Log.WriteLine (GettextCatalog.GetString ("Build cancelled"))
+ monitor.ReportError (GettextCatalog.GetString ("Build cancelled"), null)
+ if exitCode == 0:
+ exitCode = -1
+
+ error = swError.ToString()
+ return error
ensure:
+ #we get rid of this guys
+ wrapper.Dispose()
+ swError.Close()
+ chainedError.Close ()
+ operationMonitor.Dispose ()
monitor.EndTask()
- def ParseOutput (tf as TempFileCollection , context as CompilerContext) as BuildResult:
+ def ParseOutput (tf as TempFileCollection , errors as string):
cr = CompilerResults (tf)
+ # we read the errors line by line to get them in the monodevelop list
+ reader = StringReader(errors);
+ nextError as string
- for err as Boo.Lang.Compiler.CompilerError in context.Errors:
- cerror = System.CodeDom.Compiler.CompilerError ()
- cerror.ErrorText = err.Code + ": " + err.Message
-
- if err.LexicalInfo is not null:
- SetErrorLexicalInfo (cerror, err.LexicalInfo)
-
- cr.Errors.Add(cerror)
-
- for warning as CompilerWarning in context.Warnings:
- cerror = System.CodeDom.Compiler.CompilerError ()
- cerror.ErrorText = warning.Code + ": " + warning.Message
-
- if warning.LexicalInfo is not null:
- SetErrorLexicalInfo (cerror, warning.LexicalInfo)
-
- cerror.IsWarning = true
- cr.Errors.Add(cerror)
-
+ while (nextError = reader.ReadLine()) != null:
+ error = ParseErrorLine(nextError)
+ if not error is null:
+ cr.Errors.Insert(0,error)
+
+ reader.Close ();
return BuildResult (cr, null)
- def SetErrorLexicalInfo (error as System.CodeDom.Compiler.CompilerError, lexicalInfo as Boo.Lang.Compiler.Ast.LexicalInfo):
- error.FileName = lexicalInfo.FileName
- error.Column = lexicalInfo.Column
- error.Line = lexicalInfo.Line
+ private def ParseErrorLine(errorLine as string) as System.CodeDom.Compiler.CompilerError:
+ error = System.CodeDom.Compiler.CompilerError()
+ #errors are of the form "file(row, column):ErrorNum:Type:message"
+ data = @/(?<file>.*\.boo)\s*\((?<row>\d+),\s?(?<column>\d+)\):\s*(?<message>.*)/.Matches(errorLine)
+ if data.Count > 0:
+ error.ErrorText = data[0].Groups["message"].Value
+ error.FileName = data[0].Groups["file"].Value
+ error.Line = int.Parse(data[0].Groups["row"].Value)
+ error.Column = int.Parse(data[0].Groups["column"].Value)
+ if error.ErrorText.Contains("WARNING"):
+ error.IsWarning = true
+ return error
+ else:
+ return null
+
\ No newline at end of file
More information about the Monodevelop-list
mailing list