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