All pastes #247722 Raw Edit

Anonymous

public text v1 · immutable
#247722 ·published 2006-11-13 20:23 UTC
rendered paste body
Index: IgnoreFileBuildProvider.cs
===================================================================
--- IgnoreFileBuildProvider.cs  (revision 67781)
+++ IgnoreFileBuildProvider.cs  (working copy)
@@ -31,7 +31,7 @@
 #if NET_2_0
 
 namespace System.Web.Compilation {
-
+       [BuildProviderAppliesTo (BuildProviderAppliesTo.All)]
        class IgnoreFileBuildProvider : BuildProvider
        {
                public override void GenerateCode (AssemblyBuilder assemblyBuilder)
Index: WebServiceBuildProvider.cs
===================================================================
--- WebServiceBuildProvider.cs  (revision 67781)
+++ WebServiceBuildProvider.cs  (working copy)
@@ -39,7 +39,7 @@
 using System.Web.UI;
 
 namespace System.Web.Compilation {
-
+       [BuildProviderAppliesTo (BuildProviderAppliesTo.Web)]
        sealed class WebServiceBuildProvider : BuildProvider {
                WebServiceCompiler wscompiler;
                CompilerType compiler_type;
Index: PageBuildProvider.cs
===================================================================
--- PageBuildProvider.cs        (revision 67781)
+++ PageBuildProvider.cs        (working copy)
@@ -40,6 +40,7 @@
 
 namespace System.Web.Compilation {
 
+       [BuildProviderAppliesTo (BuildProviderAppliesTo.Web)]
        sealed class PageBuildProvider : BuildProvider {
                PageCompiler pcompiler;
                CompilerType compiler_type;
Index: UserControlBuildProvider.cs
===================================================================
--- UserControlBuildProvider.cs (revision 67781)
+++ UserControlBuildProvider.cs (working copy)
@@ -39,7 +39,7 @@
 using System.Web.UI;
 
 namespace System.Web.Compilation {
-
+       [BuildProviderAppliesTo (BuildProviderAppliesTo.Web)]
        sealed class UserControlBuildProvider : BuildProvider {
                UserControlCompiler uccompiler;
                CompilerType compiler_type;
Index: AssemblyBuilder.cs
===================================================================
--- AssemblyBuilder.cs  (revision 67781)
+++ AssemblyBuilder.cs  (working copy)
@@ -49,27 +49,35 @@
                CodeDomProvider provider;
                List <CodeCompileUnit> units;
                List <string> source_files;
+               List <string> referenced_assemblies;
                Dictionary <string, string> resource_files;
                TempFileCollection temp_files;
                string virtual_path;
                //TODO: there should be a Compile () method here which is where all the compilation exceptions are thrown from.
+
+               internal AssemblyBuilder (CodeDomProvider provider)
+               : this (null, provider)
+               {}
                
                internal AssemblyBuilder (string virtualPath, CodeDomProvider provider)
                {
                        this.provider = provider;
                        this.virtual_path = virtualPath;
                        units = new List <CodeCompileUnit> ();
-                       units.Add (new CodeCompileUnit ());
                        temp_files = new TempFileCollection ();
+                       referenced_assemblies = new List <string> ();
                        CompilationSection section;
-                       section = (CompilationSection) WebConfigurationManager.GetSection ("system.web/compilation", virtualPath);
+                       if (virtualPath != null)
+                               section = (CompilationSection) WebConfigurationManager.GetSection ("system.web/compilation", virtualPath);
+                       else
+                               section = (CompilationSection) WebConfigurationManager.GetSection ("system.web/compilation");
                        string tempdir = section.TempDirectory;
                        if (tempdir == null || tempdir == "")
                                tempdir = AppDomain.CurrentDomain.SetupInformation.DynamicBase;
                                
                        temp_files = new TempFileCollection (tempdir, KeepFiles);
                }
-
+               
                internal TempFileCollection TempFiles {
                        get { return temp_files; }
                }
@@ -101,14 +109,10 @@
                {
                        if (a == null)
                                throw new ArgumentNullException ("a");
-
-                       StringCollection coll = units [units.Count - 1].ReferencedAssemblies;
-                       string location = a.Location;
-                       if (coll.IndexOf (location) == -1)
-                               coll.Add (location);
+                       
+                       referenced_assemblies.Add (a.Location);
                }
 
-               [MonoTODO ("Do something with the buildProvider argument")]
                public void AddCodeCompileUnit (BuildProvider buildProvider, CodeCompileUnit compileUnit)
                {
                        if (buildProvider == null)
@@ -120,18 +124,30 @@
                        units.Add (compileUnit);
                }
 
-               [MonoTODO ("Anything to do with the buildProvider argument?")]
                public TextWriter CreateCodeFile (BuildProvider buildProvider)
                {
                        if (buildProvider == null)
                                throw new ArgumentNullException ("buildProvider");
 
-                       string filename = temp_files.AddExtension ("temp", true);
+                       // Generate a file name with the correct source language extension
+                       string filename = GetTempFilePhysicalPath (provider.FileExtension);
                        SourceFiles.Add (filename);
                        return new StreamWriter (File.OpenWrite (filename), WebEncoding.FileEncoding);
                }
 
-               [MonoTODO ("Anything to do with the buildProvider argument?")]
+               internal void AddCodeFile (string path)
+               {
+                       if (path == null || path.Length == 0)
+                               return;
+                       string extension = Path.GetExtension (path);
+                       if (extension == null || extension.Length == 0)
+                               return; // maybe better to throw an exception here?
+                       extension = extension.Substring (1);
+                       string filename = GetTempFilePhysicalPath (extension);
+                       File.Copy (path, filename, true);
+                       SourceFiles.Add (filename);
+               }
+               
                public Stream CreateEmbeddedResource (BuildProvider buildProvider, string name)
                {
                        if (buildProvider == null)
@@ -140,7 +156,7 @@
                        if (name == null || name == "")
                                throw new ArgumentNullException ("name");
 
-                       string filename = temp_files.AddExtension ("resource", true);
+                       string filename = GetTempFilePhysicalPath ("resource");
                        Stream stream = File.OpenWrite (filename);
                        ResourceFiles [name] = filename;
                        return stream;
@@ -156,19 +172,59 @@
                {
                        if (extension == null)
                                throw new ArgumentNullException ("extension");
-
-                       return temp_files.AddExtension (extension, true);
+                       
+                       return temp_files.AddExtension (String.Format ("_{0}.{1}", temp_files.Count, extension), true);
                }
 
                public CodeDomProvider CodeDomProvider {
                        get { return provider; }
                }
 
+               internal CompilerResults BuildAssembly (CompilerParameters options)
+               {
+                       return BuildAssembly (null, options);
+               }
+               
                internal CompilerResults BuildAssembly (string virtualPath, CompilerParameters options)
                {
+                       if (options == null)
+                               throw new ArgumentNullException ("options");
+                       
                        CompilerResults results;
                        CodeCompileUnit [] units = GetUnitsAsArray ();
-                       results = provider.CompileAssemblyFromDom (options, units);
+
+                       // Since we may have some source files and some code
+                       // units, we generate code from all of them and then
+                       // compile the assembly from the set of temporary source
+                       // files. This also facilates possible debugging for the
+                       // end user, since they get the code beforehand.
+                       List <string> files = SourceFiles;
+                       string filename;
+                       StreamWriter sw = null;
+                       foreach (CodeCompileUnit unit in units) {
+                               filename = GetTempFilePhysicalPath (provider.FileExtension);
+                               try {
+                                       sw = new StreamWriter (File.OpenWrite (filename), WebEncoding.FileEncoding);
+                                       provider.GenerateCodeFromCompileUnit (unit, sw, null);
+                                       files.Add (filename);
+                               } catch {
+                                       throw;
+                               } finally {
+                                       if (sw != null) {
+                                               sw.Flush ();
+                                               sw.Close ();
+                                       }
+                               }
+                       }
+
+                       Dictionary <string, string> resources = ResourceFiles;
+                       foreach (KeyValuePair <string, string> de in resources)
+                               options.EmbeddedResources.Add (de.Value);
+                       foreach (string refasm in referenced_assemblies)
+                               options.ReferencedAssemblies.Add (refasm);
+                       
+                       results = provider.CompileAssemblyFromFile (options, files.ToArray ());
+                       
                        // FIXME: generate the code and display it
                        if (results.NativeCompilerReturnValue != 0)
                                throw new CompilationException (virtualPath, results.Errors, "");
@@ -184,7 +240,8 @@
                                results.CompiledAssembly = Assembly.LoadFrom (options.OutputAssembly);
                        }
 
-                       results.TempFiles.Delete ();
+                       if (!KeepFiles)
+                               results.TempFiles.Delete ();
                        return results;
                }
        }
Index: WebHandlerBuildProvider.cs
===================================================================
--- WebHandlerBuildProvider.cs  (revision 67781)
+++ WebHandlerBuildProvider.cs  (working copy)
@@ -39,7 +39,7 @@
 using System.Web.UI;
 
 namespace System.Web.Compilation {
-
+       [BuildProviderAppliesTo (BuildProviderAppliesTo.Web)]
        sealed class WebHandlerBuildProvider : BuildProvider {
                WebServiceCompiler wscompiler;
                CompilerType compiler_type;
Index: AppCodeCompiler.cs
===================================================================
--- AppCodeCompiler.cs  (revision 67781)
+++ AppCodeCompiler.cs  (working copy)
@@ -130,30 +130,102 @@
                        }
 
                        CodeDomProvider provider = null;
-                       // First the files in the language we are aware of
-                       if (compilerInfo != null) {
+                       if (compilerInfo == null) {
+                               CompilationSection config = WebConfigurationManager.GetSection ("system.web/compilation") as CompilationSe
ction;
+                               if (config == null || !CodeDomProvider.IsDefinedLanguage (config.DefaultLanguage))
+                                       throw new HttpException ("Failed to retrieve default source language");
+                               compilerInfo = CodeDomProvider.GetCompilerInfo (config.DefaultLanguage);
+                               if (compilerInfo == null || !compilerInfo.IsCodeDomProviderTypeValid)
+                                       throw new HttpException ("Internal error while initializing application");
                                provider = compilerInfo.CreateProvider ();
                                if (provider == null)
-                                       throw new HttpException ("Unable to create a compiler for App_Code contents");
+                                       throw new HttpException ("A code provider error occurred while initializing application.");
+                       }
+                       
 
-                               CompilerParameters parameters = compilerInfo.CreateDefaultCompilerParameters ();
-                               int num = rnd.Next () + 1;
+                       //
+                       //TODO: do not compile the known files below, add them to the AssemblyBuilder instead (using SourceFiles) and
+                       //then process the unknown files with BuildProviders. After all the source files are added, use
+                       //AssemblyBuilder.BuildAssembly to generate the actual assembly.
+                       provider = compilerInfo.CreateProvider ();
+                       if (provider == null)
+                               throw new HttpException ("A code provider error occurred while initializing application.");
+
+                       AssemblyBuilder abuilder = new AssemblyBuilder (provider);
+                       foreach (string file in knownfiles)
+                               abuilder.AddCodeFile (file);
+                       
+                       BuildProvider bprovider;
+                       CompilationSection compilationSection = WebConfigurationManager.GetSection ("system.web/compilation") as CompilationSection;
+                       if (compilationSection != null) {
+                               BuildProviderCollection buildProviders = compilationSection.BuildProviders;                         

-                               string assemblyName = Path.Combine (
-                                       AppDomain.CurrentDomain.SetupInformation.DynamicBase,
-                                       String.Format ("{0}.{1}.dll", name, num.ToString ("x")));
-                               parameters.OutputAssembly = assemblyName;
-                               CompilerResults results = provider.CompileAssemblyFromFile (parameters, knownfiles.ToArray ());
-                               if (results.Errors.Count == 0) {
-                                       BuildManager.CodeAssemblies.Add (results.PathToAssembly);
-                                       BuildManager.TopLevelAssemblies.Add (results.CompiledAssembly);
-                               } else {
-                                       if (HttpContext.Current.IsCustomErrorEnabled)
-                                               throw new HttpException ("An error occurred while initializing application.");
-                                       throw new CompilationException (null, results.Errors, null);
+                               foreach (string file in unknownfiles) {
+                                       bprovider = GetBuildProviderFor (file, buildProviders);
+                                       if (bprovider == null)
+                                               continue;
+                                       bprovider.GenerateCode (abuilder);
                                }
                        }
+                       
+                       int num = rnd.Next () + 1;                              
+                       string assemblyName = Path.Combine (
+                               AppDomain.CurrentDomain.SetupInformation.DynamicBase,
+                               String.Format ("{0}.{1}.dll", name, num.ToString ("x")));
+                       CompilerParameters parameters = compilerInfo.CreateDefaultCompilerParameters ();
+                       parameters.OutputAssembly = assemblyName;
+                       CompilerResults results = abuilder.BuildAssembly (parameters);
+                       if (results.Errors.Count == 0) {
+                               BuildManager.CodeAssemblies.Add (results.PathToAssembly);
+                               BuildManager.TopLevelAssemblies.Add (results.CompiledAssembly);
+                       } else {
+                               if (HttpContext.Current.IsCustomErrorEnabled)
+                                       throw new HttpException ("An error occurred while initializing application.");
+                               throw new CompilationException (null, results.Errors, null);
+                       }
                }
+
+               private BuildProvider GetBuildProviderFor (string file, BuildProviderCollection buildProviders)
+               {
+                       if (file == null || file.Length == 0 || buildProviders == null || buildProviders.Count == 0)
+                               return null;
+
+                       foreach (BuildProvider bp in buildProviders)
+                               if (IsCorrectBuilderType (bp))
+                                       return bp;
+
+                       return null;
+               }
+
+               private bool IsCorrectBuilderType (BuildProvider bp)
+               {
+                       if (bp == null)
+                               return false;
+                       Type type;
+                       object[] attrs;
+
+                       type = bp.GetType ();
+                       attrs = type.GetCustomAttributes (true);
+                       if (attrs == null)
+                               return false;
+                       
+                       BuildProviderAppliesToAttribute bpAppliesTo;
+                       bool attributeFound = false;
+                       foreach (object attr in attrs) {
+                               bpAppliesTo = attr as BuildProviderAppliesToAttribute;
+                               if (bpAppliesTo == null)
+                                       continue;
+                               attributeFound = true;
+                               if ((bpAppliesTo.AppliesTo & BuildProviderAppliesTo.All) == BuildProviderAppliesTo.All ||
+                                   (bpAppliesTo.AppliesTo & BuildProviderAppliesTo.Code) == BuildProviderAppliesTo.Code)
+                                       return true;
+                       }
+
+                       if (attributeFound)
+                               return false;
+                       return true;
+               }
+               
        }
        
        internal class AppCodeCompiler