2004-08-09 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / System / System.CodeDom.Compiler / CodeCompiler.cs
1 //
2 // System.CodeDom.Compiler.CodeCompiler.cs
3 //
4 // Authors:
5 //   Jackson Harper (Jackson@LatitudeGeo.com)
6 //   Andreas Nahr (ClassDevelopment@A-SoftTech.com)
7 //
8 // (C) 2002 Jackson Harper, All rights reserved
9 // (C) 2003 Andreas Nahr
10 //
11
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 // 
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 // 
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 //
32
33 using System;
34 using System.IO;
35 using System.Text;
36 using System.Reflection;
37 using System.Collections;
38 using System.Collections.Specialized;
39 using System.Diagnostics;
40
41 namespace System.CodeDom.Compiler {
42
43         public abstract class CodeCompiler : CodeGenerator, ICodeCompiler
44         {
45
46                 protected CodeCompiler ()
47                 {
48                 }
49
50                 protected abstract string CompilerName {
51                         get;
52                 }
53         
54                 protected abstract string FileExtension {
55                         get;
56                 }
57
58                 protected abstract string CmdArgsFromParameters (CompilerParameters options);
59
60                 protected virtual CompilerResults FromDom (CompilerParameters options, CodeCompileUnit e)
61                 {
62                         return FromDomBatch (options, new CodeCompileUnit[]{e});
63                 }
64         
65                 protected virtual CompilerResults FromDomBatch (CompilerParameters options, CodeCompileUnit[] ea)
66                 {
67                         string[] fileNames = new string[ea.Length];
68                         int i = 0;
69                         if (options == null)
70                                 options = new CompilerParameters ();
71                         
72                         StringCollection assemblies = options.ReferencedAssemblies;
73
74                         foreach (CodeCompileUnit e in ea) {
75                                 fileNames[i] = Path.ChangeExtension (Path.GetTempFileName(), FileExtension);
76                                 FileStream f = new FileStream (fileNames[i], FileMode.OpenOrCreate);
77                                 StreamWriter s = new StreamWriter (f);
78                                 if (e.ReferencedAssemblies != null) {
79                                         foreach (string str in e.ReferencedAssemblies) {
80                                                 if (!assemblies.Contains (str))
81                                                         assemblies.Add (str);
82                                         }
83                                 }
84
85                                 ((ICodeGenerator)this).GenerateCodeFromCompileUnit (e, s, new CodeGeneratorOptions());
86                                 s.Close();
87                                 f.Close();
88                                 i++;
89                         }
90                         return Compile (options, fileNames, false);
91                 }
92
93                 protected virtual CompilerResults FromFile (CompilerParameters options, string fileName)
94                 {
95                         return FromFileBatch (options, new string[] {fileName});
96                 }
97
98                 protected virtual CompilerResults FromFileBatch (CompilerParameters options, string[] fileNames)
99                 {
100                         return Compile (options, fileNames, true);
101                 }
102
103                 protected virtual CompilerResults FromSource (CompilerParameters options, string source)
104                 {
105                         return FromSourceBatch(options, new string[]{source});
106                 }
107
108                 protected virtual CompilerResults FromSourceBatch (CompilerParameters options, string[] sources)
109                 {
110                         string[] fileNames = new string[sources.Length];
111                         int i = 0;
112                         foreach (string source in sources) {
113                                 fileNames[i] = Path.ChangeExtension (Path.GetTempFileName(), FileExtension);
114                                 FileStream f = new FileStream (fileNames[i], FileMode.OpenOrCreate);
115                                 StreamWriter s = new StreamWriter (f);
116                                 s.Write (source);
117                                 s.Close ();
118                                 f.Close ();
119                                 i++;
120                         }
121                         return Compile (options, fileNames, false);
122                 }
123
124                 private CompilerResults Compile (CompilerParameters options, string[] fileNames, bool keepFiles)
125                 {
126                         if (null == options)
127                                 throw new ArgumentNullException ("options");
128                         if (null == fileNames)
129                                 throw new ArgumentNullException ("fileNames");
130
131                         options.TempFiles = new TempFileCollection ();
132                         foreach (string file in fileNames)
133                         {
134                                 options.TempFiles.AddFile (file, keepFiles);
135                         }
136                         options.TempFiles.KeepFiles = keepFiles;
137
138                         CompilerResults results = new CompilerResults (new TempFileCollection());
139
140                         // FIXME this should probably be done by the System.CodeDom.Compiler.Executor class
141                         Process compiler = new Process();
142
143                         string compiler_output;
144                         string[] compiler_output_lines;
145                         compiler.StartInfo.FileName = CompilerName;
146                         compiler.StartInfo.Arguments = CmdArgsFromParameters (options);
147                         compiler.StartInfo.CreateNoWindow = true;
148                         compiler.StartInfo.UseShellExecute = false;
149                         compiler.StartInfo.RedirectStandardOutput = true;
150                         try {
151                                 compiler.Start();
152                                 compiler_output = compiler.StandardOutput.ReadToEnd();
153                                 compiler.WaitForExit();
154                         } 
155                         finally {
156                                 results.NativeCompilerReturnValue = compiler.ExitCode;
157                                 compiler.Close();
158                         }
159
160                         // END FIXME
161
162                         compiler_output_lines = compiler_output.Split(
163                                 System.Environment.NewLine.ToCharArray());
164                         foreach (string error_line in compiler_output_lines)
165                                 ProcessCompilerOutputLine (results, error_line);
166                         if (results.Errors.Count == 0)
167                                 results.CompiledAssembly = Assembly.LoadFrom (options.OutputAssembly);
168                         else
169                                 results.CompiledAssembly = null;
170                         return results;
171                 }
172
173                 [MonoTODO]
174                 protected virtual string GetResponseFileCmdArgs (CompilerParameters options, string cmdArgs)
175                 {
176                         // FIXME I'm not sure what this function should do...
177                         throw new NotImplementedException ();
178                 }
179
180                 CompilerResults ICodeCompiler.CompileAssemblyFromDom (CompilerParameters options, CodeCompileUnit e)
181                 {
182                         return FromDom (options, e);
183                 }
184
185                 CompilerResults ICodeCompiler.CompileAssemblyFromDomBatch (CompilerParameters options, CodeCompileUnit[] ea)
186                 {
187                         return FromDomBatch (options, ea);
188                 }
189
190                 CompilerResults ICodeCompiler.CompileAssemblyFromFile (CompilerParameters options, string fileName)
191                 {
192                         return FromFile (options, fileName);
193                 }
194
195                 CompilerResults ICodeCompiler.CompileAssemblyFromFileBatch (CompilerParameters options, string[] fileNames)
196                 {
197                         return FromFileBatch (options, fileNames);
198                 }
199
200
201                 CompilerResults ICodeCompiler.CompileAssemblyFromSource (CompilerParameters options, string source)
202                 {
203                         return FromSource (options, source);
204                 }
205
206
207                 CompilerResults ICodeCompiler.CompileAssemblyFromSourceBatch (CompilerParameters options, string[] sources)
208                 {
209                         return FromSourceBatch (options, sources);
210                 }
211
212                 protected static string JoinStringArray (string[] sa, string separator)
213                 {
214                         StringBuilder sb = new StringBuilder ();
215
216                         foreach (string s in sa)
217                                 sb.Append (s + separator);
218                         return sb.ToString ();
219                 }
220
221                 protected abstract void ProcessCompilerOutputLine (CompilerResults results, string line);
222
223         }
224 }
225