1 // Microsoft.CSharp.Compiler
4 // Jackson Harper (Jackson@LatitudeGeo.com)
6 // (C) 2002 Jackson Harper, All rights reserved.
12 using System.Collections;
13 using System.Diagnostics;
14 using System.Text.RegularExpressions;
16 namespace Microsoft.CSharp {
18 public class Compiler {
24 [MonoTODO("Have not implemented bugreports")]
25 public static CompilerError[] Compile(string[] sourceTexts,
26 string[] sourceTextNames, string target, string[] imports,
29 VerifyArgs (sourceTexts, sourceTextNames, target);
31 string[] temp_cs_files;
32 CompilerError[] errors;
33 string bugreport_path = null;
34 StreamWriter bug_report = null;
36 temp_cs_files = CreateCsFiles (sourceTexts, sourceTextNames);
39 bugreport_path = (string)options["bugreport"];
41 if (bugreport_path != null) {
42 bug_report = CreateBugReport (sourceTexts, sourceTextNames, bugreport_path);
46 errors = CompileFiles (temp_cs_files, target, imports, options, bug_report);
50 foreach (string temp_file in temp_cs_files) {
51 FileInfo file = new FileInfo (temp_file);
54 if (bug_report != null)
65 private static CompilerError[] CompileFiles (string[] cs_files,
66 string target, string[] imports, IDictionary options, StreamWriter bug_report)
68 ArrayList error_list = new ArrayList ();
69 Process mcs = new Process ();
71 string[] mcs_output_lines;
73 mcs.StartInfo.FileName = "mcs";
74 mcs.StartInfo.Arguments = BuildArgs (cs_files,
75 target, imports, options);
76 mcs.StartInfo.CreateNoWindow = true;
77 mcs.StartInfo.UseShellExecute = false;
78 mcs.StartInfo.RedirectStandardOutput = true;
82 mcs_output = mcs.StandardOutput.ReadToEnd();
88 mcs_output_lines = mcs_output.Split (
89 System.Environment.NewLine.ToCharArray ());
90 foreach (string error_line in mcs_output_lines) {
91 CompilerError error = CreateErrorFromString (error_line);
93 error_list.Add (error);
96 if (bug_report != null) {
97 bug_report.WriteLine ("### Compiler Output");
98 bug_report.Write (mcs_output);
101 return (CompilerError[])error_list.ToArray (typeof(CompilerError));
105 /// Converts an error string into a CompilerError object
106 /// Return null if the line was not an error string
108 private static CompilerError CreateErrorFromString(string error_string)
110 CompilerError error = new CompilerError();
111 Regex reg = new Regex (@"^((?<file>.*)\((?<line>\d*)(,(?<column>\d*))?\)\s){0,}(?<level>\w+)\sCS(?<number>\d*):\s(?<message>.*)",
112 RegexOptions.Compiled | RegexOptions.ExplicitCapture);
114 Match match = reg.Match (error_string);
119 if (String.Empty != match.Result ("${file}"))
120 error.SourceFile = match.Result ("${file}");
121 if (String.Empty != match.Result ("${line}"))
122 error.SourceLine = Int32.Parse (match.Result ("${line}"));
123 if (String.Empty != match.Result ("${column}"))
124 error.SourceColumn = Int32.Parse (match.Result ("${column}"));
125 error.ErrorLevel = (ErrorLevel)Enum.Parse (typeof(ErrorLevel),
126 match.Result ("${level}"), true);
127 error.ErrorNumber = Int32.Parse (match.Result ("${number}"));
128 error.ErrorMessage = match.Result ("${message}");
133 private static string[] CreateCsFiles (string[] source_text, string[] source_name)
135 ArrayList temp_file_list = new ArrayList ();
137 for (int i=0; i<source_text.Length; i++) {
138 string temp_path = Path.GetTempFileName ();
139 StreamWriter writer = null;
141 writer = new StreamWriter (temp_path);
142 writer.WriteLine (String.Format ("#line 1 \"{0}\"",
144 writer.Write (source_text[i]);
150 temp_file_list.Add (temp_path);
153 return (string[])temp_file_list.ToArray (typeof(string));
156 private static string BuildArgs(string[] source_files,
157 string target, string[] imports, IDictionary options)
159 StringBuilder args = new StringBuilder ();
161 args.AppendFormat ("/out:{0} ", target);
163 if (null != imports) {
164 foreach (string import in imports)
165 args.AppendFormat ("/r:{0} ", import);
168 if (null != options) {
169 foreach (object option in options.Keys) {
170 object value = options[option];
171 if (!ValidOption ((string)option))
173 args.AppendFormat ("{0} ", OptionString (option,value));
177 foreach (string source in source_files)
178 args.AppendFormat ("{0} ", source);
180 return args.ToString ();
183 private static string OptionString(object option, object value)
186 return String.Format ("/{0}:{1}", option, value);
188 return String.Format("/{0}", option);
191 private static void VerifyArgs (string[] sourceTexts,
192 string[] sourceTextNames, string target)
194 if (null == sourceTexts)
195 throw new ArgumentNullException ("sourceTexts");
196 if (null == sourceTextNames)
197 throw new ArgumentNullException ("sourceTextNames");
199 throw new ArgumentNullException ("target");
201 if (sourceTexts.Length <= 0 || sourceTextNames.Length <= 0)
202 throw new IndexOutOfRangeException ();
205 private static StreamWriter CreateBugReport (string[] source_texts,
206 string[] source_names, string path)
208 StreamWriter bug_report = null;
211 bug_report = new StreamWriter (path);
212 bug_report.WriteLine ("### C# Compiler Defect Report," +
213 " created {0}", DateTime.Now);
218 for (int i=0; i<source_texts.Length; i++) {
219 bug_report.WriteLine ("### Source file: '{0}'",
221 bug_report.Write (source_texts[i]);
224 if (bug_report != null)
233 private static bool ValidOption (string option)