[Mono-list] CSharpCompiler patch

Sean Kasun skasun@azstarnet.com
Fri, 10 Jan 2003 12:37:50 -0700


Index: list
===================================================================
RCS file: /mono/mcs/class/System/list,v
retrieving revision 1.11
diff -u -p -r1.11 list
--- list	7 Dec 2002 22:16:41 -0000	1.11
+++ list	10 Jan 2003 19:21:07 -0000
@@ -148,3 +148,4 @@ System.Diagnostics\TraceListener.cs
 System.Net\IPv6Address.cs
 Microsoft.CSharp\CSharpCodeProvider.cs
 Microsoft.CSharp\CSharpCodeGenerator.cs
+Microsoft.CSharp\CSharpCodeCompiler.cs
Index: list.unix
===================================================================
RCS file: /mono/mcs/class/System/list.unix,v
retrieving revision 1.31
diff -u -p -r1.31 list.unix
--- list.unix	7 Dec 2002 22:24:16 -0000	1.31
+++ list.unix	10 Jan 2003 19:21:07 -0000
@@ -350,3 +350,4 @@ System.Timers/TimersDescriptionAttribute
 System.Security.Cryptography.X509Certificates/X509CertificateCollection.cs
 Microsoft.CSharp/CSharpCodeProvider.cs
 Microsoft.CSharp/CSharpCodeGenerator.cs
+Microsoft.CSharp/CSharpCodeCompiler.cs
Index: Microsoft.CSharp/CSharpCodeCompiler.cs
===================================================================
RCS file: Microsoft.CSharp/CSharpCodeCompiler.cs
diff -N Microsoft.CSharp/CSharpCodeCompiler.cs
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Microsoft.CSharp/CSharpCodeCompiler.cs	10 Jan 2003 19:21:07 -0000
@@ -0,0 +1,171 @@
+//
+// Mono.CSharp CSharpCodeCompiler Class implementation
+//
+// Author:
+//   Sean Kasun (seank@users.sf.net)
+//
+
+namespace Mono.CSharp
+{
+	using System;
+	using System.CodeDom;
+	using System.CodeDom.Compiler;
+	using System.IO;
+	using System.Text;
+	using System.Reflection;
+	using System.Collections;
+	using System.Diagnostics;
+	using System.Text.RegularExpressions;
+
+	internal class CSharpCodeCompiler : CSharpCodeGenerator, ICodeCompiler
+	{
+		//
+		// Constructors
+		//
+		public CSharpCodeCompiler()
+		{
+		}
+
+		//
+		// Methods
+		//
+		[MonoTODO]
+		public CompilerResults CompileAssemblyFromDom (
+			CompilerParameters options,CodeCompileUnit e)
+		{
+			return CompileAssemblyFromDomBatch(options,new CodeCompileUnit[]{e});
+		}
+		public CompilerResults CompileAssemblyFromDomBatch (
+			CompilerParameters options,CodeCompileUnit[] ea)
+		{
+			string[] fileNames=new string[ea.Length];
+			int i=0;
+			foreach (CodeCompileUnit e in ea)
+			{
+				fileNames[i]=Path.ChangeExtension(Path.GetTempFileName(),"cs");
+				FileStream f=new FileStream(fileNames[i],FileMode.OpenOrCreate);
+				StreamWriter s=new StreamWriter(f);
+
+				GenerateCodeFromCompileUnit(e,s,new CodeGeneratorOptions());
+				s.Close();
+				f.Close();
+				i++;
+			}
+			return CompileAssemblyFromFileBatch(options,fileNames);
+		}
+		public CompilerResults CompileAssemblyFromFile (
+			CompilerParameters options,string fileName)
+		{
+			return CompileAssemblyFromFileBatch(options,new string[]{fileName});
+		}
+		public CompilerResults CompileAssemblyFromFileBatch (
+			CompilerParameters options,string[] fileNames)
+		{
+			if (null == options)
+				throw new ArgumentNullException("options");
+			if (null == fileNames)
+				throw new ArgumentNullException("fileNames");
+
+			CompilerResults results=new CompilerResults(options.TempFiles);
+			Process mcs=new Process();
+
+			string mcs_output;
+			string[] mcs_output_lines;
+			mcs.StartInfo.FileName="mcs";
+			mcs.StartInfo.Arguments=BuildArgs(options,fileNames);
+			mcs.StartInfo.CreateNoWindow=true;
+			mcs.StartInfo.UseShellExecute=false;
+			mcs.StartInfo.RedirectStandardOutput=true;
+			try {
+				mcs.Start();
+				mcs_output=mcs.StandardOutput.ReadToEnd();
+				mcs.WaitForExit();
+			} finally {
+				mcs.Close();
+			}
+			mcs_output_lines=mcs_output.Split(
+				System.Environment.NewLine.ToCharArray());
+			bool loadIt=true;
+			foreach (string error_line in mcs_output_lines)
+			{
+				CompilerError error=CreateErrorFromString(error_line);
+				if (null!=error)
+				{
+					results.Errors.Add(error);
+					if (!error.IsWarning) loadIt=false;
+				}
+			}
+			if (loadIt)
+				results.CompiledAssembly=Assembly.LoadFrom(options.OutputAssembly);
+			else
+				results.CompiledAssembly=null;
+			return results;
+		}
+		public CompilerResults CompileAssemblyFromSource (
+			CompilerParameters options,string source)
+		{
+			return CompileAssemblyFromSourceBatch(options,new string[]{source});
+		}
+		public CompilerResults CompileAssemblyFromSourceBatch (
+			CompilerParameters options,string[] sources)
+		{
+			string[] fileNames=new string[sources.Length];
+			int i=0;
+			foreach (string source in sources)
+			{
+				fileNames[i]=Path.ChangeExtension(Path.GetTempFileName(),"cs");
+				FileStream f=new FileStream(fileNames[i],FileMode.OpenOrCreate);
+				StreamWriter s=new StreamWriter(f);
+				s.Write(source);
+				s.Close();
+				f.Close();
+				i++;
+			}
+			return CompileAssemblyFromFileBatch(options,fileNames);
+		}
+		private static string BuildArgs(
+			CompilerParameters options,string[] fileNames)
+		{
+			StringBuilder args=new StringBuilder();
+			if (options.GenerateExecutables)
+				args.AppendFormat("/target:exe ");
+			else
+				args.AppendFormat("/target:library ");
+			if (options.IncludeDebugInformation)
+				args.AppendFormat("/debug ");
+			if (options.TreatWarningsAsErrors)
+				args.AppendFormat("/warnaserror ");
+			args.AppendFormat("/warn:{0} ",options.WarningLevel);
+			if (options.OutputAssembly==null)
+				options.OutputAssembly=Path.ChangeExtension(Path.GetTempFileName(),"dll");
+			args.AppendFormat("/out:{0} ",options.OutputAssembly);
+			if (null != options.ReferencedAssemblies)
+			{
+				foreach (string import in options.ReferencedAssemblies)
+					args.AppendFormat("/r:'{0}' ",import);
+			}
+			foreach (string source in fileNames)
+				args.AppendFormat("'{0}' ",source);
+			return args.ToString();
+		}
+		private static CompilerError CreateErrorFromString(string error_string)
+		{
+			CompilerError error=new CompilerError();
+			Regex reg = new Regex (@"^(\s*(?<file>.*)\((?<line>\d*)(,(?<column>\d*))?\)\s+)*(?<level>\w+)\s*(?<number>.*):\s(?<message>.*)",
+				RegexOptions.Compiled | RegexOptions.ExplicitCapture);
+			Match match=reg.Match(error_string);
+			if (!match.Success) return null;
+			if (String.Empty != match.Result("${file}"))
+				error.FileName=match.Result("${file}");
+			if (String.Empty != match.Result("${line}"))
+				error.Line=Int32.Parse(match.Result("${line}"));
+			if (String.Empty != match.Result("${column}"))
+				error.Column=Int32.Parse(match.Result("${column}"));
+			if (match.Result("${level}")=="warning")
+				error.IsWarning=true;
+			error.ErrorNumber=match.Result("${number}");
+			error.ErrorText=match.Result("${message}");
+			return error;
+		}
+	}
+}
Index: Microsoft.CSharp/CSharpCodeProvider.cs
===================================================================
RCS file: /mono/mcs/class/System/Microsoft.CSharp/CSharpCodeProvider.cs,v
retrieving revision 1.2
diff -u -p -r1.2 CSharpCodeProvider.cs
--- Microsoft.CSharp/CSharpCodeProvider.cs	12 Oct 2002 02:02:24 -0000	1.2
+++ Microsoft.CSharp/CSharpCodeProvider.cs	10 Jan 2003 19:21:07 -0000
@@ -35,10 +35,9 @@ namespace Microsoft.CSharp
 		//
 		// Methods
 		//
-		[MonoTODO]
 		public override ICodeCompiler CreateCompiler()
 		{
-			throw new NotImplementedException();
+			return new Mono.CSharp.CSharpCodeCompiler();
 		}
 
 		public override ICodeGenerator CreateGenerator()
Index: System.CodeDom.Compiler/CompilerErrorCollection.cs
===================================================================
RCS file: /mono/mcs/class/System/System.CodeDom.Compiler/CompilerErrorCollection.cs,v
retrieving revision 1.2
diff -u -p -r1.2 CompilerErrorCollection.cs
--- System.CodeDom.Compiler/CompilerErrorCollection.cs	23 Aug 2002 06:24:31 -0000	1.2
+++ System.CodeDom.Compiler/CompilerErrorCollection.cs	10 Jan 2003 19:21:08 -0000
@@ -16,96 +16,81 @@ namespace System.CodeDom.Compiler
 		[MonoTODO]
 		public CompilerErrorCollection ()
 		{
-			throw new NotImplementedException ();
 		}
 
-		[MonoTODO]
 		public CompilerErrorCollection (CompilerErrorCollection value)
 		{
-			throw new NotImplementedException ();
+			InnerList.AddRange(value.InnerList);
 		}
 
-		[MonoTODO]
 		public CompilerErrorCollection (CompilerError[] value)
 		{
-			throw new NotImplementedException ();
+			InnerList.AddRange(value);
 		}
 
-		[MonoTODO]
 		public int Add (CompilerError value)
 		{
-			throw new NotImplementedException ();
+			return InnerList.Add(value);
 		}
 
-		[MonoTODO]
 		public void AddRange (CompilerError[] value)
 		{
-			throw new NotImplementedException ();
+			InnerList.AddRange(value);
 		}
 
-		[MonoTODO]
 		public void AddRange (CompilerErrorCollection value)
 		{
-			throw new NotImplementedException ();
+			InnerList.AddRange(value.InnerList);
 		}
 
-		[MonoTODO]
 		public bool Contains (CompilerError value)
 		{
-			throw new NotImplementedException ();
+			return InnerList.Contains(value);
 		}
 
-		[MonoTODO]
 		public void CopyTo (CompilerError[] array, int index)
 		{
-			throw new NotImplementedException ();
+			InnerList.CopyTo(array,index);
 		}
 
-		[MonoTODO]
 		public int IndexOf (CompilerError value)
 		{
-			throw new NotImplementedException ();
+			return InnerList.IndexOf(value);
 		}
 
-		[MonoTODO]
 		public void Insert (int index, CompilerError value)
 		{
-			throw new NotImplementedException ();
+			InnerList.Insert(index,value);
 		}
 
-		[MonoTODO]
 		public void Remove (CompilerError value)
 		{
-			throw new NotImplementedException ();
+			InnerList.Remove(value);
 		}
 
-		[MonoTODO]
 		public CompilerError this [int index]
 		{
-			get {
-				throw new NotImplementedException ();
-			}
-			set {
-				throw new NotImplementedException ();
-			}
+			get { return (CompilerError) InnerList[index]; }
+			set { InnerList[index]=value; }
 		}
 
-		[MonoTODO]
 		public bool HasErrors
 		{
 			get {
-				throw new NotImplementedException ();
+				foreach (CompilerError error in InnerList)
+					if (!error.IsWarning) return true;
+				return false;
 			}
 		}
 
-		[MonoTODO]
 		public bool HasWarnings
 		{
 			get {
-				throw new NotImplementedException ();
+				foreach (CompilerError error in InnerList)
+					if (error.IsWarning) return true;
+				return false;
 			}
 		}
 	}
-
 }
 
Index: System.CodeDom.Compiler/CompilerParameters.cs
===================================================================
RCS file: /mono/mcs/class/System/System.CodeDom.Compiler/CompilerParameters.cs,v
retrieving revision 1.1
diff -u -p -r1.1 CompilerParameters.cs
--- System.CodeDom.Compiler/CompilerParameters.cs	28 May 2002 06:59:57 -0000	1.1
+++ System.CodeDom.Compiler/CompilerParameters.cs	10 Jan 2003 19:21:08 -0000
@@ -35,14 +35,23 @@ namespace System.CodeDom.Compiler
 		
 		public CompilerParameters( string[] assemblyNames )
 		{
+			referencedAssemblies=new StringCollection();
+			referencedAssemblies.AddRange(assemblyNames);
 		}
 
 		public CompilerParameters( string[] assemblyNames, string output )
 		{
+			referencedAssemblies=new StringCollection();
+			referencedAssemblies.AddRange(assemblyNames);
+			outputAssembly=output;
 		}
 
 		public CompilerParameters( string[] assemblyNames, string output, bool includeDebugInfo )
 		{
+			referencedAssemblies=new StringCollection();
+			referencedAssemblies.AddRange(assemblyNames);
+			outputAssembly=output;
+			includeDebugInformation=includeDebugInfo;
 		}