Moved StreamWriter creation into a try block
[mono.git] / mcs / class / Cscompmgd / Microsoft.CSharp / Compiler.cs
1 // Microsoft.CSharp.Compiler
2 //
3 // Author(s):
4 //  Jackson Harper (Jackson@LatitudeGeo.com)
5 //
6 // (C) 2002 Jackson Harper, All rights reserved.
7 //
8
9 using System;
10 using System.IO;
11 using System.Text;
12 using System.Collections;
13 using System.Diagnostics;
14 using System.Text.RegularExpressions;
15
16 namespace Microsoft.CSharp {
17
18         public class Compiler {
19                 
20                 public Compiler()
21                 {
22                 }
23
24                 [MonoTODO("Have not implemented bugreports")]
25                 public static CompilerError[] Compile(string[] sourceTexts,
26                         string[] sourceTextNames, string target, string[] imports,
27                         IDictionary options)
28                 {
29                         VerifyArgs (sourceTexts, sourceTextNames, target);
30                         
31                         string[] temp_cs_files;
32                         CompilerError[] errors;
33
34                         temp_cs_files = CreateCsFiles (sourceTexts, sourceTextNames);
35                         
36                         try {
37                                 errors = CompileFiles (temp_cs_files, target, imports, options);
38                         } catch {
39                                 throw;
40                         } finally {
41                                 foreach (string temp_file in temp_cs_files) {
42                                         FileInfo file = new FileInfo (temp_file);
43                                         file.Delete ();
44                                 }
45                         }
46                         
47                         return errors;
48                 }
49                 
50                 //
51                 // Private Methods
52                 //
53
54                 private static CompilerError[] CompileFiles (string[] cs_files,
55                         string target, string[] imports, IDictionary options) 
56                 {
57                         ArrayList error_list = new ArrayList ();
58                         Process mcs = new Process ();
59                         string mcs_output;
60                         string[] mcs_output_lines;
61
62                         mcs.StartInfo.FileName = "mcs";
63                         mcs.StartInfo.Arguments = BuildArgs (cs_files, 
64                                 target, imports, options);
65                         mcs.StartInfo.CreateNoWindow = true;
66                         mcs.StartInfo.UseShellExecute = false;
67                         mcs.StartInfo.RedirectStandardOutput = true;
68
69                         try {
70                                 mcs.Start ();
71                                 mcs_output = mcs.StandardOutput.ReadToEnd();
72                                 mcs.WaitForExit ();
73                         } finally {
74                                 mcs.Close ();
75                         }
76                         
77                         mcs_output_lines = mcs_output.Split (
78                                 System.Environment.NewLine.ToCharArray ());
79                         foreach (string error_line in mcs_output_lines) {
80                                 CompilerError error = CreateErrorFromString (error_line);
81                                 if (null != error)
82                                         error_list.Add (error); 
83                         }
84                         
85                         return (CompilerError[])error_list.ToArray (typeof(CompilerError));
86                 }
87
88                 /// <summary>
89                 ///   Converts an error string into a CompilerError object
90                 ///   Return null if the line was not an error string
91                 /// </summary>
92                 private static CompilerError CreateErrorFromString(string error_string) 
93                 {
94                         CompilerError error = new CompilerError();
95                         Regex reg = new Regex (@"^((?<file>.*)\((?<line>\d*)(,(?<column>\d*))?\)\s){0,}(?<level>\w+)\sCS(?<number>\d*):\s(?<message>.*)", 
96                         RegexOptions.Compiled | RegexOptions.ExplicitCapture);
97
98                         Match match = reg.Match (error_string);
99                         
100                         if (!match.Success)
101                                 return null;
102                         
103                         if (String.Empty != match.Result ("${file}"))
104                                 error.SourceFile = match.Result ("${file}");
105                         if (String.Empty != match.Result ("${line}"))
106                                 error.SourceLine = Int32.Parse (match.Result ("${line}"));
107                         if (String.Empty != match.Result ("${column}"))
108                                 error.SourceColumn = Int32.Parse (match.Result ("${column}"));
109                         error.ErrorLevel = (ErrorLevel)Enum.Parse (typeof(ErrorLevel),
110                                 match.Result ("${level}"), true);
111                         error.ErrorNumber = Int32.Parse (match.Result ("${number}"));
112                         error.ErrorMessage = match.Result ("${message}");
113                         
114                         return error;
115                 }
116
117                 private static string[] CreateCsFiles (string[] source_text, string[] source_name) 
118                 {
119                         ArrayList temp_file_list = new ArrayList ();
120
121                         for (int i=0; i<source_text.Length; i++) {
122                                 string temp_path = Path.GetTempFileName ();
123                                 StreamWriter writer = null;
124                                 try {
125                                         writer = new StreamWriter (temp_path);
126                                         writer.WriteLine (String.Format ("#line 1 \"{0}\"", 
127                                                 source_name[i]));
128                                         writer.Write (source_text[i]);
129                                 } catch {
130                                 } finally {
131                                         if (writer != null)
132                                                 writer.Close ();
133                                 }
134                                 temp_file_list.Add (temp_path);
135                         }
136                 
137                         return (string[])temp_file_list.ToArray (typeof(string));       
138                 }
139
140                 private static string BuildArgs(string[] source_files,
141                         string target, string[] imports, IDictionary options)
142                 {
143                         StringBuilder args = new StringBuilder ();
144
145                         args.AppendFormat ("/out:{0} ", target);
146                         
147                         if (null != imports) {
148                                 foreach (string import in imports)
149                                         args.AppendFormat ("/r:{0} ", import);
150                         }
151                         
152                         if (null != options) {
153                                 foreach (object option in options.Keys) {
154                                         object value = options[option];
155                                         args.AppendFormat ("{0} ", OptionString (option,value));
156                                 }
157                         }
158                         
159                         foreach (string source in source_files)
160                                 args.AppendFormat ("{0} ", source);
161
162                         return args.ToString ();
163                 }
164
165                 private static string OptionString(object option, object value)
166                 {
167                         if (null != value)
168                                 return String.Format ("/{0}:{1}", option, value);
169                         
170                         return String.Format("/{0}", option);
171                 }
172
173                 private static void VerifyArgs (string[] sourceTexts,
174                         string[] sourceTextNames, string target)
175                 {
176                         if (null == sourceTexts)
177                                 throw new ArgumentNullException ("sourceTexts");
178                         if (null == sourceTextNames)
179                                 throw new ArgumentNullException ("sourceTextNames");
180                         if (null == target)
181                                 throw new ArgumentNullException ("target");
182
183                         if (sourceTexts.Length <= 0 || sourceTextNames.Length <= 0)
184                                 throw new IndexOutOfRangeException ();
185                 }
186
187         }
188
189 }
190