2 // Microsoft VisualBasic VBCodeCompiler Class implementation
\r
5 // Jochen Wezel (jwezel@compumaster.de)
\r
8 namespace Microsoft.VisualBasic
\r
11 using System.CodeDom;
\r
12 using System.CodeDom.Compiler;
\r
15 using System.Reflection;
\r
16 using System.Collections;
\r
17 using System.Collections.Specialized;
\r
18 using System.Diagnostics;
\r
19 using System.Text.RegularExpressions;
\r
21 internal class VisualBasicCodeCompiler: VisualBasicCodeGenerator, ICodeCompiler
\r
26 public VisualBasicCodeCompiler()
\r
34 public CompilerResults CompileAssemblyFromDom (
\r
35 CompilerParameters options,CodeCompileUnit e)
\r
37 return CompileAssemblyFromDomBatch(options,new CodeCompileUnit[]{e});
\r
39 public CompilerResults CompileAssemblyFromDomBatch (
\r
40 CompilerParameters options,CodeCompileUnit[] ea)
\r
42 string[] fileNames=new string[ea.Length];
\r
44 if (options == null)
\r
45 options = new CompilerParameters ();
\r
47 StringCollection assemblies = options.ReferencedAssemblies;
\r
49 foreach (CodeCompileUnit e in ea)
\r
51 fileNames[i]=Path.ChangeExtension(Path.GetTempFileName(),"vb");
\r
52 FileStream f=new FileStream(fileNames[i],FileMode.OpenOrCreate);
\r
53 StreamWriter s=new StreamWriter(f);
\r
54 if (e.ReferencedAssemblies != null) {
\r
55 foreach (string str in e.ReferencedAssemblies) {
\r
56 if (!assemblies.Contains (str))
\r
57 assemblies.Add (str);
\r
61 ((ICodeGenerator)this).GenerateCodeFromCompileUnit (e, s, new CodeGeneratorOptions());
\r
66 return CompileAssemblyFromFileBatch(options,fileNames);
\r
68 public CompilerResults CompileAssemblyFromFile (
\r
69 CompilerParameters options,string fileName)
\r
71 return CompileAssemblyFromFileBatch(options,new string[]{fileName});
\r
73 public CompilerResults CompileAssemblyFromFileBatch (
\r
74 CompilerParameters options,string[] fileNames)
\r
76 if (null == options)
\r
77 throw new ArgumentNullException("options");
\r
78 if (null == fileNames)
\r
79 throw new ArgumentNullException("fileNames");
\r
81 CompilerResults results=new CompilerResults(options.TempFiles);
\r
82 Process mcs=new Process();
\r
85 string[] mcs_output_lines;
\r
86 mcs.StartInfo.FileName="mbas";
\r
87 mcs.StartInfo.Arguments=BuildArgs(options,fileNames);
\r
88 mcs.StartInfo.CreateNoWindow=true;
\r
89 mcs.StartInfo.UseShellExecute=false;
\r
90 mcs.StartInfo.RedirectStandardOutput=true;
\r
93 mcs_output=mcs.StandardOutput.ReadToEnd();
\r
96 results.NativeCompilerReturnValue = mcs.ExitCode;
\r
99 mcs_output_lines=mcs_output.Split(
\r
100 System.Environment.NewLine.ToCharArray());
\r
102 foreach (string error_line in mcs_output_lines)
\r
104 CompilerError error=CreateErrorFromString(error_line);
\r
107 results.Errors.Add(error);
\r
108 if (!error.IsWarning) loadIt=false;
\r
112 results.CompiledAssembly=Assembly.LoadFrom(options.OutputAssembly);
\r
114 results.CompiledAssembly=null;
\r
117 public CompilerResults CompileAssemblyFromSource (
\r
118 CompilerParameters options,string source)
\r
120 return CompileAssemblyFromSourceBatch(options,new string[]{source});
\r
122 public CompilerResults CompileAssemblyFromSourceBatch (
\r
123 CompilerParameters options,string[] sources)
\r
125 string[] fileNames=new string[sources.Length];
\r
127 foreach (string source in sources)
\r
129 fileNames[i]=Path.ChangeExtension(Path.GetTempFileName(),"vb");
\r
130 FileStream f=new FileStream(fileNames[i],FileMode.OpenOrCreate);
\r
131 StreamWriter s=new StreamWriter(f);
\r
137 return CompileAssemblyFromFileBatch(options,fileNames);
\r
139 private static string BuildArgs(
\r
140 CompilerParameters options,string[] fileNames)
\r
142 StringBuilder args=new StringBuilder();
\r
143 if (options.GenerateExecutable)
\r
144 args.AppendFormat("/target:exe ");
\r
146 args.AppendFormat("/target:library ");
\r
147 if (options.IncludeDebugInformation)
\r
148 args.AppendFormat("/debug ");
\r
149 if (options.TreatWarningsAsErrors)
\r
150 args.AppendFormat("/warnaserror ");
\r
152 if (options.WarningLevel != -1)
\r
153 args.AppendFormat ("/warn:{0} ", options.WarningLevel);
\r
155 if (options.OutputAssembly==null)
\r
156 options.OutputAssembly=Path.ChangeExtension(Path.GetTempFileName(),"dll");
\r
157 args.AppendFormat("/out:\"{0}\" ",options.OutputAssembly);
\r
158 if (null != options.ReferencedAssemblies)
\r
160 foreach (string import in options.ReferencedAssemblies)
\r
161 args.AppendFormat("/r:\"{0}\" ",import);
\r
163 foreach (string source in fileNames)
\r
164 args.AppendFormat("\"{0}\" ",source);
\r
165 return args.ToString();
\r
167 private static CompilerError CreateErrorFromString(string error_string)
\r
169 // When IncludeDebugInformation is true, prevents the debug symbols stats from braeking this.
\r
170 if (error_string.StartsWith ("WROTE SYMFILE") || error_string.StartsWith ("OffsetTable"))
\r
173 CompilerError error=new CompilerError();
\r
174 Regex reg = new Regex (@"^(\s*(?<file>.*)\((?<line>\d*)(,(?<column>\d*))?\)\s+)*(?<level>\w+)\s*(?<number>.*):\s(?<message>.*)",
\r
175 RegexOptions.Compiled | RegexOptions.ExplicitCapture);
\r
176 Match match=reg.Match(error_string);
\r
177 if (!match.Success) return null;
\r
178 if (String.Empty != match.Result("${file}"))
\r
179 error.FileName=match.Result("${file}");
\r
180 if (String.Empty != match.Result("${line}"))
\r
181 error.Line=Int32.Parse(match.Result("${line}"));
\r
182 if (String.Empty != match.Result("${column}"))
\r
183 error.Column=Int32.Parse(match.Result("${column}"));
\r
184 if (match.Result("${level}")=="warning")
\r
185 error.IsWarning=true;
\r
186 error.ErrorNumber=match.Result("${number}");
\r
187 error.ErrorText=match.Result("${message}");
\r