BuildProvidersCompiler.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / whidbey / netfxsp / ndp / fx / src / xsp / System / Web / Compilation / BuildProvidersCompiler.cs / 4 / BuildProvidersCompiler.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

 
 
namespace System.Web.Compilation {
 
using System;
using System.IO;
using System.Collections;
using System.Collections.Specialized; 
using System.Reflection;
using System.Globalization; 
using System.CodeDom; 
using System.CodeDom.Compiler;
using System.Configuration; 
using System.Web.Hosting;
using System.Web.Util;
using System.Web.Caching;
using System.Web.UI; 
using System.Web.Configuration;
 
internal class BuildProvidersCompiler { 
    private ICollection _buildProviders;
    private VirtualPath _configPath; 
    private bool _supportLocalization;

    // The set of assemblies that we need to reference when compiling
    private ICollection _referencedAssemblies; 
    internal ICollection ReferencedAssemblies { get { return _referencedAssemblies; } }
 
    private AssemblyBuilder _assemblyBuilder; 

    // Key: CultureName string, Value: AssemblyBuilder 
    private IDictionary _satelliteAssemblyBuilders = null;

    // If this is set, we only generate the source files into this directory
    // without compiling them. 
    // This is used to implement ClientBuildManager.GetCodeDirectoryInformation
    private string _generatedFilesDir; 
 
    internal BuildProvidersCompiler(VirtualPath configPath, string outputAssemblyName) :
        this(configPath, false, outputAssemblyName) { } 

    internal BuildProvidersCompiler(VirtualPath configPath, bool supportLocalization,
        string outputAssemblyName) {
        _configPath = configPath; 
        _supportLocalization = supportLocalization;
        _compConfig = RuntimeConfig.GetConfig(_configPath).Compilation; 
        _referencedAssemblies = BuildManager.GetReferencedAssemblies(CompConfig); 
        _outputAssemblyName = outputAssemblyName;
    } 

    internal BuildProvidersCompiler(VirtualPath configPath, bool supportLocalization,
        string generatedFilesDir, int index) {
        _configPath = configPath; 
        _supportLocalization = supportLocalization;
        _compConfig = RuntimeConfig.GetConfig(_configPath).Compilation; 
        _referencedAssemblies = BuildManager.GetReferencedAssemblies(CompConfig, index); 
        _generatedFilesDir = generatedFilesDir;
    } 

    // The  config section for the set of build providers that we handle
    private CompilationSection _compConfig;
    internal CompilationSection CompConfig { get { return _compConfig; } } 

    private string _outputAssemblyName; 
    internal string OutputAssemblyName { 
        get { return _outputAssemblyName; }
    } 

    private bool CbmGenerateOnlyMode {
        get { return _generatedFilesDir != null; }
    } 

    internal void SetBuildProviders(ICollection buildProviders) { 
        _buildProviders = buildProviders; 
    }
 
    private void ProcessBuildProviders() {

        CompilerType compilerType = null;
        BuildProvider firstLanguageBuildProvider = null; 

        // First, delete all the existing satellite assemblies of the assembly 
        // we're about to build (VSWhidbey 87022) (only if it has a fixed name) 
        if (OutputAssemblyName != null) {
            Debug.Assert(!CbmGenerateOnlyMode); 
            StandardDiskBuildResultCache.RemoveSatelliteAssemblies(OutputAssemblyName);
        }

        // List of BuildProvider's that don't ask for a specific language 
        ArrayList languageFreeBuildProviders = null;
 
        foreach (BuildProvider buildProvider in _buildProviders) { 

            // If it's an InternalBuildProvider, give it the assembly references early on 
            buildProvider.SetReferencedAssemblies(_referencedAssemblies);

            // Instruct the internal build providers to continue processing for more parse errors.
            if (!BuildManager.ThrowOnFirstParseError) { 
                InternalBuildProvider provider = buildProvider as InternalBuildProvider;
                if (provider != null) { 
                    provider.ThrowOnFirstParseError = false; 
                }
            } 

            // Get the language and culture
            CompilerType ctwp = BuildProvider.GetCompilerTypeFromBuildProvider(buildProvider);
 
            // Only look for a culture if we're supposed to (basically, in the resources directories)
            string cultureName = null; 
            if (_supportLocalization) 
                cultureName = buildProvider.GetCultureName();
 
            // Is it asking for a specific language?
            if (ctwp != null) {

                // If it specifies a language, it can't also have a culture 
                if (cultureName != null) {
                    throw new HttpException(SR.GetString( 
                        SR.Both_culture_and_language, BuildProvider.GetDisplayName(buildProvider))); 
                }
 
                // Do we already know the language we'll be using
                if (compilerType != null) {

                    // If it's different from the current one, fail 
                    if (!ctwp.Equals(compilerType)) {
                        throw new HttpException(SR.GetString( 
                            SR.Inconsistent_language, 
                            BuildProvider.GetDisplayName(buildProvider),
                            BuildProvider.GetDisplayName(firstLanguageBuildProvider))); 
                    }
                }
                else {
                    // Keep track of the build provider of error handling purpose 
                    firstLanguageBuildProvider = buildProvider;
 
                    // Keep track of the language 
                    compilerType = ctwp;
                    _assemblyBuilder = compilerType.CreateAssemblyBuilder( 
                        CompConfig, _referencedAssemblies, _generatedFilesDir, OutputAssemblyName);
                }
            }
            else { 
                if (cultureName != null) {
                    // Ignore the culture files in generate-only mode 
                    if (CbmGenerateOnlyMode) 
                        continue;
 
                    if (_satelliteAssemblyBuilders == null) {
                        _satelliteAssemblyBuilders = new Hashtable(
                            StringComparer.OrdinalIgnoreCase);
                    } 

                    // Check if we already have an assembly builder for this culture 
                    AssemblyBuilder satelliteAssemblyBuilder = 
                        (AssemblyBuilder) _satelliteAssemblyBuilders[cultureName];
 
                    // If not, create one and store it in the hashtable
                    if (satelliteAssemblyBuilder == null) {
                        satelliteAssemblyBuilder = CompilerType.GetDefaultAssemblyBuilder(
                            CompConfig, _referencedAssemblies, _configPath, OutputAssemblyName); 
                        satelliteAssemblyBuilder.CultureName = cultureName;
                        _satelliteAssemblyBuilders[cultureName] = satelliteAssemblyBuilder; 
                    } 

                    satelliteAssemblyBuilder.AddBuildProvider(buildProvider); 
                    continue;
                }

                if (_assemblyBuilder == null) { 
                    // If this provider doesn't need a specific language, and we don't know
                    // the language yet, just keep track of it 
                    if (languageFreeBuildProviders == null) 
                        languageFreeBuildProviders = new ArrayList();
                    languageFreeBuildProviders.Add(buildProvider); 
                    continue;
                }
            }
 
            _assemblyBuilder.AddBuildProvider(buildProvider);
        } 
 
        // If we didn't get an AssemblyBuilder, use a default
        if (_assemblyBuilder == null && languageFreeBuildProviders != null) { 
            _assemblyBuilder = CompilerType.GetDefaultAssemblyBuilder(
                CompConfig, _referencedAssemblies, _configPath,
                _generatedFilesDir, OutputAssemblyName);
        } 

        // Add all the language free providers (if any) to the AssemblyBuilder 
        if (_assemblyBuilder != null && languageFreeBuildProviders != null) { 
            foreach (BuildProvider languageFreeBuildProvider in languageFreeBuildProviders) {
                _assemblyBuilder.AddBuildProvider(languageFreeBuildProvider); 
            }
        }
    }
 
    internal CompilerResults PerformBuild() {
 
        ProcessBuildProviders(); 

        // Build all the satellite assemblies 
        if (_satelliteAssemblyBuilders != null) {
            foreach (AssemblyBuilder satelliteAssemblyBuilder in _satelliteAssemblyBuilders.Values) {
                satelliteAssemblyBuilder.Compile();
            } 
        }
 
        // Build the main assembly 
        if (_assemblyBuilder != null)
            return _assemblyBuilder.Compile(); 

        return null;
    }
 
    internal void GenerateSources(out Type codeDomProviderType,
        out CompilerParameters compilerParameters) { 
 
        ProcessBuildProviders();
 
        // If we didn't get an AssemblyBuilder (happens when there was nothing to build),
        // get a default one.
        if (_assemblyBuilder == null) {
            _assemblyBuilder = CompilerType.GetDefaultAssemblyBuilder( 
                CompConfig, _referencedAssemblies, _configPath,
                _generatedFilesDir, null /*outputAssemblyName*/); 
        } 

        codeDomProviderType = _assemblyBuilder.CodeDomProviderType; 
        compilerParameters = _assemblyBuilder.GetCompilerParameters();
    }
}
 

/* 
 * This class handles the batch compilation of one directory.  It may 
 * produce several assemblies out of them, based on dependencies and language
 * differences.  All the BuildProvider's are expected to share the same 
 * configuration (i.e. they live in the same directory).
 */
internal class WebDirectoryBatchCompiler {
 
    private DateTime _utcStart;
 
    // The set of assemblies that we will link with 
    private ICollection _referencedAssemblies;
 
    // The  config section for the set of build providers that we handle
    private CompilationSection _compConfig;

    // [VirtualPathString,InternalBuildProvider] 
    private IDictionary _buildProviders = new Hashtable(
        StringComparer.OrdinalIgnoreCase); 
 
    private VirtualDirectory _vdir;
    private ArrayList[] _nonDependentBuckets; 

    private bool _ignoreProvidersWithErrors;

    // The set of parser errors detected during parsing. 
    private ParserErrorCollection _parserErrors;
 
    // The first parse exceptions thrown during parsing. 
    private HttpParseException _firstException;
 
    internal WebDirectoryBatchCompiler(VirtualDirectory vdir) {
        _vdir = vdir;

        _utcStart = DateTime.UtcNow; 

        _compConfig = RuntimeConfig.GetConfig(_vdir.VirtualPath).Compilation; 
 
        _referencedAssemblies = BuildManager.GetReferencedAssemblies(_compConfig);
    } 

    internal void SetIgnoreErrors() {
        _ignoreProvidersWithErrors = true;
    } 

    internal void Process() { 
 
        AddBuildProviders(true /*retryIfDeletionHappens*/);
 
        // If there are no BuildProvider's, we're done
        if (_buildProviders.Count == 0)
            return;
 
        BuildManager.ReportDirectoryCompilationProgress(_vdir.VirtualPathObject);
 
        GetBuildResultDependencies(); 
        ProcessDependencies();
 
        foreach (ICollection buildProviders in _nonDependentBuckets) {
            if (!CompileNonDependentBuildProviders(buildProviders))
                break;
        } 

        // Report all parse exceptions 
        if (_parserErrors != null && _parserErrors.Count > 0) { 
            Debug.Assert(!_ignoreProvidersWithErrors);
 
            // Throw the first exception as inner exception along with the parse errors.
            HttpParseException newException =
                new HttpParseException(_firstException.Message, _firstException, _firstException.VirtualPath,
                    _firstException.Source, _firstException.Line); 

            // Add the rest of the parser errors to the exception. 
            // The first one is already added. 
            for (int i = 1; i < _parserErrors.Count; i++) {
                newException.ParserErrors.Add(_parserErrors[i]); 
            }

            // rethrow the new exception
            throw newException; 
        }
    } 
 
    private void AddBuildProviders(bool retryIfDeletionHappens) {
 
        DiskBuildResultCache.ResetAssemblyDeleted();

        foreach (VirtualFile vfile in _vdir.Files) {
 
            // If it's already built and up to date, skip it
            BuildResult result = null; 
            try { 
                result = BuildManager.GetVPathBuildResultFromCache(vfile.VirtualPathObject);
            } 
            catch {
                // Ignore the cached error in batch compilation mode, since we want to compile
                // as many files as possible.
                // But don't ignore it in CBM or precompile cases, since we always want to try 
                // to compile everything that had failed before.
                if (!BuildManager.PerformingPrecompilation) { 
                    // Skip it if an exception occurs (e.g. if a compile error was cached for it) 
                    continue;
                } 
            }

            if (result != null)
                continue; 

            BuildProvider buildProvider = BuildManager.CreateBuildProvider(vfile.VirtualPathObject, 
                _compConfig, _referencedAssemblies, false /*failIfUnknown*/); 

            // Non-supported file type 
            if (buildProvider == null)
                continue;

            // IgnoreFileBuildProvider's should never be created 
            Debug.Assert(!(buildProvider is IgnoreFileBuildProvider));
 
            _buildProviders[vfile.VirtualPath] = buildProvider; 
        }
 
        // If an assembly had to be deleted/renamed as a result of calling GetVPathBuildResultFromCache,
        // me way need to run the AddBuildProviders logic again.  The reason is that as a result of
        // deleting the assembly, we may have invalidated other BuildResult that we had earlier found
        // to be up to date (VSWhidbey 269297) 
        if (DiskBuildResultCache.InUseAssemblyWasDeleted) {
            Debug.Assert(retryIfDeletionHappens); 
 
            // Only retry if we're doing precompilation.  For standard batching, we can live
            // with the fact that not everything will be built after we're done (and we want to 
            // be done as quickly as possible since the user is waiting).
            if (retryIfDeletionHappens && BuildManager.PerformingPrecompilation) {
                Debug.Trace("WebDirectoryBatchCompiler", "Rerunning AddBuildProviders for '" +
                    _vdir.VirtualPath + "' because an assembly was out of date."); 

                // Pass false for retryIfDeletionHappens to make sure we don't get in an 
                // infinite recursion. 
                AddBuildProviders(false /*retryIfDeletionHappens*/);
            } 
        }
    }

    private void CacheAssemblyResults(AssemblyBuilder assemblyBuilder, CompilerResults results) { 

        foreach (BuildProvider buildProvider in assemblyBuilder.BuildProviders) { 
 
            BuildResult result = buildProvider.GetBuildResult(results);
 
            // If the provider didn't produce anything, ignore it
            if (result == null)
                continue;
 
            // If CacheVPathBuildResult returns false, something was found to be invalidated
            // and we need to abort the caching (VSWhidbey 578372) 
            if (!BuildManager.CacheVPathBuildResult(buildProvider.VirtualPathObject, result, _utcStart)) 
                break;
 
#if DBG
            if (results != null) {
                Debug.Trace("BuildManager", buildProvider.VirtualPath + results.CompiledAssembly.EscapedCodeBase);
            } 
            else {
                Debug.Trace("BuildManager", buildProvider.VirtualPath + ": no assembly"); 
            } 
#endif
        } 
    }

    // Cache the various compile errors found during batching
    private void CacheCompileErrors(AssemblyBuilder assemblyBuilder, CompilerResults results) { 

        BuildProvider previous = null; 
 
        // Go through all the compile errors
        foreach (CompilerError error in results.Errors) { 

            // Skip warnings
            if (error.IsWarning)
                continue; 

            // Try to map the error back to a BuildProvider.  If we can't, skip the error. 
            BuildProvider buildProvider = assemblyBuilder.GetBuildProviderFromLinePragma(error.FileName); 
            if (buildProvider == null)
                continue; 

            // Only cache the error for template controls.  Otherwise, for file types like
            // asmx/ashx, it's too likely that two of them define the same class.
            if (!(buildProvider is BaseTemplateBuildProvider)) 
                continue;
 
            // If the error is for the same page as the previous one, ignore it 
            if (buildProvider == previous)
                continue; 
            previous = buildProvider;

            // Create a new CompilerResults for this error
            CompilerResults newResults = new CompilerResults(null /*tempFiles*/); 

            // Copy all the output to the new result.  Note that this will include all the 
            // error lines, not just the ones for this BuildProvider.  But that's not a big deal, 
            // and we can't easily filter the output here.
            foreach (string s in results.Output) 
                newResults.Output.Add(s);

            // Copy various other fields to the new CompilerResults object
            newResults.PathToAssembly = results.PathToAssembly; 
            newResults.NativeCompilerReturnValue = results.NativeCompilerReturnValue;
 
            // Add this error.  It will be the only one in the CompilerResults object. 
            newResults.Errors.Add(error);
 
            // Create a new HttpCompileException & BuildResultCompileError to wrap this error
            HttpCompileException e = new HttpCompileException(newResults,
                assemblyBuilder.GetGeneratedSourceFromBuildProvider(buildProvider));
            BuildResult result = new BuildResultCompileError(buildProvider.VirtualPathObject, e); 

            // Add the dependencies to the compile error build provider, so that 
            // we will retry compilation when a dependency changes 
            buildProvider.SetBuildResultDependencies(result);
 
            // Cache it
            BuildManager.CacheVPathBuildResult(buildProvider.VirtualPathObject, result, _utcStart);
        }
 
    }
 
    private void GetBuildResultDependencies() { 
        foreach (BuildProvider buildProvider in _buildProviders.Values) {
            ICollection virtualPathDependencies = buildProvider.GetBuildResultVirtualPathDependencies(); 
            if (virtualPathDependencies == null)
                continue;

            foreach (string virtualPathDependency in virtualPathDependencies) { 
                BuildProvider dependentBuildProvider = (BuildProvider) _buildProviders[virtualPathDependency];
 
                if (dependentBuildProvider != null) 
                    buildProvider.AddBuildProviderDependency(dependentBuildProvider);
            } 
        }
    }

    // Split the providers into non dependent buckets 
    private void ProcessDependencies() {
        // First phase: compute levels in the dependency tree 
 
        int totaldepth = 0;
        Hashtable depth = new Hashtable(); 
        Stack stack = new Stack();

        // compute depths
        foreach (BuildProvider buildProvider in _buildProviders.Values) { 
            stack.Push(buildProvider);
 
            while (stack.Count > 0) { 
                BuildProvider curnode = (BuildProvider)stack.Peek();
 
                bool recurse = false;
                int maxdepth = 0;

                if (curnode.BuildProviderDependencies != null) { 
                    foreach (BuildProvider child in curnode.BuildProviderDependencies) {
 
                        if (depth.ContainsKey(child)) { 
                            if (maxdepth <= (int)depth[child])
                                maxdepth = (int)depth[child] + 1; 
                            else if ((int)depth[child] == -1)
                                throw new HttpException(SR.GetString(SR.File_Circular_Reference, child.VirtualPath));
                        }
                        else { 
                            recurse = true;
                            stack.Push(child); 
                        } 
                    }
                } 

                if (recurse)
                    depth[curnode] = -1; // being computed;
                else { 
                    stack.Pop();
                    depth[curnode] = maxdepth; 
                    if (totaldepth <= maxdepth) 
                        totaldepth = maxdepth + 1;
                } 
            }
        }

        // drop into buckets by depth 
        _nonDependentBuckets = new ArrayList[totaldepth];
 
        for (IDictionaryEnumerator en = (IDictionaryEnumerator)depth.GetEnumerator(); en.MoveNext();) { 
            int level = (int)en.Value;
 
            if (_nonDependentBuckets[level] == null)
                _nonDependentBuckets[level] = new ArrayList();

            _nonDependentBuckets[level].Add(en.Key); 
        }
 
#if DBG 
        int i = 0;
        foreach (ICollection buildProviders in _nonDependentBuckets) { 
            Debug.Trace("BuildManager", String.Empty);
            Debug.Trace("BuildManager", "Bucket " + i + " contains " + buildProviders.Count + " files");

            foreach (BuildProvider buildProvider in buildProviders) 
                Debug.Trace("BuildManager", buildProvider.VirtualPath);
            i++; 
        } 
#endif
 
    }

    private bool IsBuildProviderSkipable(BuildProvider buildProvider) {
 
        // If another build provider depends on it, we should not skip it
        if (buildProvider.IsDependedOn) return false; 
 
        // No one depends on it (at least in this directory)
 
        // If it's a source file, skip it.  We need to do this for v1 compatibility,
        // since v1 VS projects contain many source files which have already been
        // precompiled into bin, and that should not be compiled dynamically
        if (buildProvider is SourceFileBuildProvider) 
            return true;
 
        // For the same reason, skip resources 
        if (buildProvider is ResXBuildProvider)
            return true; 

        return false;
    }
 
    private bool CompileNonDependentBuildProviders(ICollection buildProviders) {
 
        // Key: CompilerType, Value: AssemblyBuilder 
        IDictionary assemblyBuilders = new Hashtable();
 
        // List of InternalBuildProvider's that don't ask for a specific language
        ArrayList languageFreeBuildProviders = null;

        // AssemblyBuilder used for providers that don't need a specific language 
        AssemblyBuilder defaultAssemblyBuilder = null;
 
        bool hasParserErrors = false; 

        foreach (BuildProvider buildProvider in buildProviders) { 

            if (IsBuildProviderSkipable(buildProvider))
                continue;
 
            // Instruct the internal build providers to continue processing for more parse errors.
            if (!BuildManager.ThrowOnFirstParseError) { 
                InternalBuildProvider provider = buildProvider as InternalBuildProvider; 
                if (provider != null) {
                    provider.ThrowOnFirstParseError = false; 
                }
            }

            CompilerType compilerType = null; 

            // Get the language 
            try { 
                compilerType = BuildProvider.GetCompilerTypeFromBuildProvider(
                    buildProvider); 
            }
            catch (HttpParseException ex) {
                // Ignore the error if we are in that mode.
                if (_ignoreProvidersWithErrors) { 
                    continue;
                } 
 
                hasParserErrors = true;
 
                // Remember the first parse exception
                if (_firstException == null) {
                    _firstException = ex;
                } 

                if (_parserErrors == null) { 
                    _parserErrors = new ParserErrorCollection(); 
                }
 
                _parserErrors.AddRange(ex.ParserErrors);

                continue;
            } 
            catch {
                // Ignore the error if we are in that mode. 
                if (_ignoreProvidersWithErrors) { 
                    continue;
                } 

                throw;
            }
 
            AssemblyBuilder assemblyBuilder = defaultAssemblyBuilder;
 
            // Is it asking for a specific language? 
            if (compilerType == null) {
                // If this provider doesn't need a specific language, and we haven't created 
                // a default builder yet, just keep track of it
                if (defaultAssemblyBuilder == null) {
                    if (languageFreeBuildProviders == null) {
                        languageFreeBuildProviders = new ArrayList(); 
                    }
 
                    languageFreeBuildProviders.Add(buildProvider); 
                    continue;
                } 
            }
            else {
                // Check if we already have an assembly builder of the right type
                assemblyBuilder = (AssemblyBuilder)assemblyBuilders[compilerType]; 
            }
 
            ICollection typeNames = buildProvider.GetGeneratedTypeNames(); 

            // Starts a new assemblyBuilder if the old one already contains another buildprovider 
            // that uses the same type name
            if (assemblyBuilder == null || assemblyBuilder.IsBatchFull ||
                assemblyBuilder.ContainsTypeNames(typeNames)) {
 
                // If the assemblyBuilder is full, compile it.
                if (assemblyBuilder != null) { 
                    CompileAssemblyBuilder(assemblyBuilder); 
                }
 
                AssemblyBuilder newBuilder = compilerType.CreateAssemblyBuilder(
                    _compConfig, _referencedAssemblies);

                assemblyBuilders[compilerType] = newBuilder; 

                // Remember it as the default if we don't already have one, 
                // or if the default is already full, switch the default to the new one. 
                if (defaultAssemblyBuilder == null ||
                    defaultAssemblyBuilder == assemblyBuilder) { 

                    defaultAssemblyBuilder = newBuilder;
                }
 
                assemblyBuilder = newBuilder;
            } 
 
            assemblyBuilder.AddTypeNames(typeNames);
            assemblyBuilder.AddBuildProvider(buildProvider); 
        }

        // Don't try to compile providers, otherwise compile exceptions will be bubbled up,
        // and we lose the parse errors. 
        if (hasParserErrors) {
            return false; 
        } 

        // Handle all the left over language free providers 
        if (languageFreeBuildProviders != null) {

            // Indicates whether the default assembly builder is not a language specific builder.
            bool newDefaultAssemblyBuilder = (defaultAssemblyBuilder == null); 

            // Add language independent providers to the default assembly builder. 
            foreach (BuildProvider languageFreeBuildProvider in languageFreeBuildProviders) { 

                ICollection typeNames = languageFreeBuildProvider.GetGeneratedTypeNames(); 

                // If we don't have a default language assembly builder, get one or
                // starts a new assemblyBuilder if the old one already contains another buildprovider
                // that uses the same type name 
                if (defaultAssemblyBuilder == null || defaultAssemblyBuilder.IsBatchFull ||
                    defaultAssemblyBuilder.ContainsTypeNames(typeNames)) { 
 
                    // If the default assemblyBuilder is full, compile it.
                    if (defaultAssemblyBuilder != null) { 
                        CompileAssemblyBuilder(defaultAssemblyBuilder);
                    }

                    defaultAssemblyBuilder = CompilerType.GetDefaultAssemblyBuilder( 
                        _compConfig, _referencedAssemblies, _vdir.VirtualPathObject /*configPath*/,
                        null /*outputAssemblyName*/); 
 
                    // the default assembly builder needs to be compiled separately.
                    newDefaultAssemblyBuilder = true; 
                }

                defaultAssemblyBuilder.AddTypeNames(typeNames);
                defaultAssemblyBuilder.AddBuildProvider(languageFreeBuildProvider); 
            }
 
            // Only compile the default assembly builder if it's not part of language specific 
            // assembly builder (which will be compiled separately)
            if (newDefaultAssemblyBuilder) { 
                // Compile the default assembly builder.
                CompileAssemblyBuilder(defaultAssemblyBuilder);
            }
        } 

        foreach (AssemblyBuilder assemblyBuilder in assemblyBuilders.Values) { 
            CompileAssemblyBuilder(assemblyBuilder); 
        }
 
        return true;
    }

    private void CompileAssemblyBuilder(AssemblyBuilder builder) { 

        CompilerResults results; 
 
        try {
            results = builder.Compile(); 
        }
        catch (HttpCompileException e) {
            CacheCompileErrors(builder, e.Results);
            throw; 
        }
 
        CacheAssemblyResults(builder, results); 
    }
} 

}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

 
 
namespace System.Web.Compilation {
 
using System;
using System.IO;
using System.Collections;
using System.Collections.Specialized; 
using System.Reflection;
using System.Globalization; 
using System.CodeDom; 
using System.CodeDom.Compiler;
using System.Configuration; 
using System.Web.Hosting;
using System.Web.Util;
using System.Web.Caching;
using System.Web.UI; 
using System.Web.Configuration;
 
internal class BuildProvidersCompiler { 
    private ICollection _buildProviders;
    private VirtualPath _configPath; 
    private bool _supportLocalization;

    // The set of assemblies that we need to reference when compiling
    private ICollection _referencedAssemblies; 
    internal ICollection ReferencedAssemblies { get { return _referencedAssemblies; } }
 
    private AssemblyBuilder _assemblyBuilder; 

    // Key: CultureName string, Value: AssemblyBuilder 
    private IDictionary _satelliteAssemblyBuilders = null;

    // If this is set, we only generate the source files into this directory
    // without compiling them. 
    // This is used to implement ClientBuildManager.GetCodeDirectoryInformation
    private string _generatedFilesDir; 
 
    internal BuildProvidersCompiler(VirtualPath configPath, string outputAssemblyName) :
        this(configPath, false, outputAssemblyName) { } 

    internal BuildProvidersCompiler(VirtualPath configPath, bool supportLocalization,
        string outputAssemblyName) {
        _configPath = configPath; 
        _supportLocalization = supportLocalization;
        _compConfig = RuntimeConfig.GetConfig(_configPath).Compilation; 
        _referencedAssemblies = BuildManager.GetReferencedAssemblies(CompConfig); 
        _outputAssemblyName = outputAssemblyName;
    } 

    internal BuildProvidersCompiler(VirtualPath configPath, bool supportLocalization,
        string generatedFilesDir, int index) {
        _configPath = configPath; 
        _supportLocalization = supportLocalization;
        _compConfig = RuntimeConfig.GetConfig(_configPath).Compilation; 
        _referencedAssemblies = BuildManager.GetReferencedAssemblies(CompConfig, index); 
        _generatedFilesDir = generatedFilesDir;
    } 

    // The  config section for the set of build providers that we handle
    private CompilationSection _compConfig;
    internal CompilationSection CompConfig { get { return _compConfig; } } 

    private string _outputAssemblyName; 
    internal string OutputAssemblyName { 
        get { return _outputAssemblyName; }
    } 

    private bool CbmGenerateOnlyMode {
        get { return _generatedFilesDir != null; }
    } 

    internal void SetBuildProviders(ICollection buildProviders) { 
        _buildProviders = buildProviders; 
    }
 
    private void ProcessBuildProviders() {

        CompilerType compilerType = null;
        BuildProvider firstLanguageBuildProvider = null; 

        // First, delete all the existing satellite assemblies of the assembly 
        // we're about to build (VSWhidbey 87022) (only if it has a fixed name) 
        if (OutputAssemblyName != null) {
            Debug.Assert(!CbmGenerateOnlyMode); 
            StandardDiskBuildResultCache.RemoveSatelliteAssemblies(OutputAssemblyName);
        }

        // List of BuildProvider's that don't ask for a specific language 
        ArrayList languageFreeBuildProviders = null;
 
        foreach (BuildProvider buildProvider in _buildProviders) { 

            // If it's an InternalBuildProvider, give it the assembly references early on 
            buildProvider.SetReferencedAssemblies(_referencedAssemblies);

            // Instruct the internal build providers to continue processing for more parse errors.
            if (!BuildManager.ThrowOnFirstParseError) { 
                InternalBuildProvider provider = buildProvider as InternalBuildProvider;
                if (provider != null) { 
                    provider.ThrowOnFirstParseError = false; 
                }
            } 

            // Get the language and culture
            CompilerType ctwp = BuildProvider.GetCompilerTypeFromBuildProvider(buildProvider);
 
            // Only look for a culture if we're supposed to (basically, in the resources directories)
            string cultureName = null; 
            if (_supportLocalization) 
                cultureName = buildProvider.GetCultureName();
 
            // Is it asking for a specific language?
            if (ctwp != null) {

                // If it specifies a language, it can't also have a culture 
                if (cultureName != null) {
                    throw new HttpException(SR.GetString( 
                        SR.Both_culture_and_language, BuildProvider.GetDisplayName(buildProvider))); 
                }
 
                // Do we already know the language we'll be using
                if (compilerType != null) {

                    // If it's different from the current one, fail 
                    if (!ctwp.Equals(compilerType)) {
                        throw new HttpException(SR.GetString( 
                            SR.Inconsistent_language, 
                            BuildProvider.GetDisplayName(buildProvider),
                            BuildProvider.GetDisplayName(firstLanguageBuildProvider))); 
                    }
                }
                else {
                    // Keep track of the build provider of error handling purpose 
                    firstLanguageBuildProvider = buildProvider;
 
                    // Keep track of the language 
                    compilerType = ctwp;
                    _assemblyBuilder = compilerType.CreateAssemblyBuilder( 
                        CompConfig, _referencedAssemblies, _generatedFilesDir, OutputAssemblyName);
                }
            }
            else { 
                if (cultureName != null) {
                    // Ignore the culture files in generate-only mode 
                    if (CbmGenerateOnlyMode) 
                        continue;
 
                    if (_satelliteAssemblyBuilders == null) {
                        _satelliteAssemblyBuilders = new Hashtable(
                            StringComparer.OrdinalIgnoreCase);
                    } 

                    // Check if we already have an assembly builder for this culture 
                    AssemblyBuilder satelliteAssemblyBuilder = 
                        (AssemblyBuilder) _satelliteAssemblyBuilders[cultureName];
 
                    // If not, create one and store it in the hashtable
                    if (satelliteAssemblyBuilder == null) {
                        satelliteAssemblyBuilder = CompilerType.GetDefaultAssemblyBuilder(
                            CompConfig, _referencedAssemblies, _configPath, OutputAssemblyName); 
                        satelliteAssemblyBuilder.CultureName = cultureName;
                        _satelliteAssemblyBuilders[cultureName] = satelliteAssemblyBuilder; 
                    } 

                    satelliteAssemblyBuilder.AddBuildProvider(buildProvider); 
                    continue;
                }

                if (_assemblyBuilder == null) { 
                    // If this provider doesn't need a specific language, and we don't know
                    // the language yet, just keep track of it 
                    if (languageFreeBuildProviders == null) 
                        languageFreeBuildProviders = new ArrayList();
                    languageFreeBuildProviders.Add(buildProvider); 
                    continue;
                }
            }
 
            _assemblyBuilder.AddBuildProvider(buildProvider);
        } 
 
        // If we didn't get an AssemblyBuilder, use a default
        if (_assemblyBuilder == null && languageFreeBuildProviders != null) { 
            _assemblyBuilder = CompilerType.GetDefaultAssemblyBuilder(
                CompConfig, _referencedAssemblies, _configPath,
                _generatedFilesDir, OutputAssemblyName);
        } 

        // Add all the language free providers (if any) to the AssemblyBuilder 
        if (_assemblyBuilder != null && languageFreeBuildProviders != null) { 
            foreach (BuildProvider languageFreeBuildProvider in languageFreeBuildProviders) {
                _assemblyBuilder.AddBuildProvider(languageFreeBuildProvider); 
            }
        }
    }
 
    internal CompilerResults PerformBuild() {
 
        ProcessBuildProviders(); 

        // Build all the satellite assemblies 
        if (_satelliteAssemblyBuilders != null) {
            foreach (AssemblyBuilder satelliteAssemblyBuilder in _satelliteAssemblyBuilders.Values) {
                satelliteAssemblyBuilder.Compile();
            } 
        }
 
        // Build the main assembly 
        if (_assemblyBuilder != null)
            return _assemblyBuilder.Compile(); 

        return null;
    }
 
    internal void GenerateSources(out Type codeDomProviderType,
        out CompilerParameters compilerParameters) { 
 
        ProcessBuildProviders();
 
        // If we didn't get an AssemblyBuilder (happens when there was nothing to build),
        // get a default one.
        if (_assemblyBuilder == null) {
            _assemblyBuilder = CompilerType.GetDefaultAssemblyBuilder( 
                CompConfig, _referencedAssemblies, _configPath,
                _generatedFilesDir, null /*outputAssemblyName*/); 
        } 

        codeDomProviderType = _assemblyBuilder.CodeDomProviderType; 
        compilerParameters = _assemblyBuilder.GetCompilerParameters();
    }
}
 

/* 
 * This class handles the batch compilation of one directory.  It may 
 * produce several assemblies out of them, based on dependencies and language
 * differences.  All the BuildProvider's are expected to share the same 
 * configuration (i.e. they live in the same directory).
 */
internal class WebDirectoryBatchCompiler {
 
    private DateTime _utcStart;
 
    // The set of assemblies that we will link with 
    private ICollection _referencedAssemblies;
 
    // The  config section for the set of build providers that we handle
    private CompilationSection _compConfig;

    // [VirtualPathString,InternalBuildProvider] 
    private IDictionary _buildProviders = new Hashtable(
        StringComparer.OrdinalIgnoreCase); 
 
    private VirtualDirectory _vdir;
    private ArrayList[] _nonDependentBuckets; 

    private bool _ignoreProvidersWithErrors;

    // The set of parser errors detected during parsing. 
    private ParserErrorCollection _parserErrors;
 
    // The first parse exceptions thrown during parsing. 
    private HttpParseException _firstException;
 
    internal WebDirectoryBatchCompiler(VirtualDirectory vdir) {
        _vdir = vdir;

        _utcStart = DateTime.UtcNow; 

        _compConfig = RuntimeConfig.GetConfig(_vdir.VirtualPath).Compilation; 
 
        _referencedAssemblies = BuildManager.GetReferencedAssemblies(_compConfig);
    } 

    internal void SetIgnoreErrors() {
        _ignoreProvidersWithErrors = true;
    } 

    internal void Process() { 
 
        AddBuildProviders(true /*retryIfDeletionHappens*/);
 
        // If there are no BuildProvider's, we're done
        if (_buildProviders.Count == 0)
            return;
 
        BuildManager.ReportDirectoryCompilationProgress(_vdir.VirtualPathObject);
 
        GetBuildResultDependencies(); 
        ProcessDependencies();
 
        foreach (ICollection buildProviders in _nonDependentBuckets) {
            if (!CompileNonDependentBuildProviders(buildProviders))
                break;
        } 

        // Report all parse exceptions 
        if (_parserErrors != null && _parserErrors.Count > 0) { 
            Debug.Assert(!_ignoreProvidersWithErrors);
 
            // Throw the first exception as inner exception along with the parse errors.
            HttpParseException newException =
                new HttpParseException(_firstException.Message, _firstException, _firstException.VirtualPath,
                    _firstException.Source, _firstException.Line); 

            // Add the rest of the parser errors to the exception. 
            // The first one is already added. 
            for (int i = 1; i < _parserErrors.Count; i++) {
                newException.ParserErrors.Add(_parserErrors[i]); 
            }

            // rethrow the new exception
            throw newException; 
        }
    } 
 
    private void AddBuildProviders(bool retryIfDeletionHappens) {
 
        DiskBuildResultCache.ResetAssemblyDeleted();

        foreach (VirtualFile vfile in _vdir.Files) {
 
            // If it's already built and up to date, skip it
            BuildResult result = null; 
            try { 
                result = BuildManager.GetVPathBuildResultFromCache(vfile.VirtualPathObject);
            } 
            catch {
                // Ignore the cached error in batch compilation mode, since we want to compile
                // as many files as possible.
                // But don't ignore it in CBM or precompile cases, since we always want to try 
                // to compile everything that had failed before.
                if (!BuildManager.PerformingPrecompilation) { 
                    // Skip it if an exception occurs (e.g. if a compile error was cached for it) 
                    continue;
                } 
            }

            if (result != null)
                continue; 

            BuildProvider buildProvider = BuildManager.CreateBuildProvider(vfile.VirtualPathObject, 
                _compConfig, _referencedAssemblies, false /*failIfUnknown*/); 

            // Non-supported file type 
            if (buildProvider == null)
                continue;

            // IgnoreFileBuildProvider's should never be created 
            Debug.Assert(!(buildProvider is IgnoreFileBuildProvider));
 
            _buildProviders[vfile.VirtualPath] = buildProvider; 
        }
 
        // If an assembly had to be deleted/renamed as a result of calling GetVPathBuildResultFromCache,
        // me way need to run the AddBuildProviders logic again.  The reason is that as a result of
        // deleting the assembly, we may have invalidated other BuildResult that we had earlier found
        // to be up to date (VSWhidbey 269297) 
        if (DiskBuildResultCache.InUseAssemblyWasDeleted) {
            Debug.Assert(retryIfDeletionHappens); 
 
            // Only retry if we're doing precompilation.  For standard batching, we can live
            // with the fact that not everything will be built after we're done (and we want to 
            // be done as quickly as possible since the user is waiting).
            if (retryIfDeletionHappens && BuildManager.PerformingPrecompilation) {
                Debug.Trace("WebDirectoryBatchCompiler", "Rerunning AddBuildProviders for '" +
                    _vdir.VirtualPath + "' because an assembly was out of date."); 

                // Pass false for retryIfDeletionHappens to make sure we don't get in an 
                // infinite recursion. 
                AddBuildProviders(false /*retryIfDeletionHappens*/);
            } 
        }
    }

    private void CacheAssemblyResults(AssemblyBuilder assemblyBuilder, CompilerResults results) { 

        foreach (BuildProvider buildProvider in assemblyBuilder.BuildProviders) { 
 
            BuildResult result = buildProvider.GetBuildResult(results);
 
            // If the provider didn't produce anything, ignore it
            if (result == null)
                continue;
 
            // If CacheVPathBuildResult returns false, something was found to be invalidated
            // and we need to abort the caching (VSWhidbey 578372) 
            if (!BuildManager.CacheVPathBuildResult(buildProvider.VirtualPathObject, result, _utcStart)) 
                break;
 
#if DBG
            if (results != null) {
                Debug.Trace("BuildManager", buildProvider.VirtualPath + results.CompiledAssembly.EscapedCodeBase);
            } 
            else {
                Debug.Trace("BuildManager", buildProvider.VirtualPath + ": no assembly"); 
            } 
#endif
        } 
    }

    // Cache the various compile errors found during batching
    private void CacheCompileErrors(AssemblyBuilder assemblyBuilder, CompilerResults results) { 

        BuildProvider previous = null; 
 
        // Go through all the compile errors
        foreach (CompilerError error in results.Errors) { 

            // Skip warnings
            if (error.IsWarning)
                continue; 

            // Try to map the error back to a BuildProvider.  If we can't, skip the error. 
            BuildProvider buildProvider = assemblyBuilder.GetBuildProviderFromLinePragma(error.FileName); 
            if (buildProvider == null)
                continue; 

            // Only cache the error for template controls.  Otherwise, for file types like
            // asmx/ashx, it's too likely that two of them define the same class.
            if (!(buildProvider is BaseTemplateBuildProvider)) 
                continue;
 
            // If the error is for the same page as the previous one, ignore it 
            if (buildProvider == previous)
                continue; 
            previous = buildProvider;

            // Create a new CompilerResults for this error
            CompilerResults newResults = new CompilerResults(null /*tempFiles*/); 

            // Copy all the output to the new result.  Note that this will include all the 
            // error lines, not just the ones for this BuildProvider.  But that's not a big deal, 
            // and we can't easily filter the output here.
            foreach (string s in results.Output) 
                newResults.Output.Add(s);

            // Copy various other fields to the new CompilerResults object
            newResults.PathToAssembly = results.PathToAssembly; 
            newResults.NativeCompilerReturnValue = results.NativeCompilerReturnValue;
 
            // Add this error.  It will be the only one in the CompilerResults object. 
            newResults.Errors.Add(error);
 
            // Create a new HttpCompileException & BuildResultCompileError to wrap this error
            HttpCompileException e = new HttpCompileException(newResults,
                assemblyBuilder.GetGeneratedSourceFromBuildProvider(buildProvider));
            BuildResult result = new BuildResultCompileError(buildProvider.VirtualPathObject, e); 

            // Add the dependencies to the compile error build provider, so that 
            // we will retry compilation when a dependency changes 
            buildProvider.SetBuildResultDependencies(result);
 
            // Cache it
            BuildManager.CacheVPathBuildResult(buildProvider.VirtualPathObject, result, _utcStart);
        }
 
    }
 
    private void GetBuildResultDependencies() { 
        foreach (BuildProvider buildProvider in _buildProviders.Values) {
            ICollection virtualPathDependencies = buildProvider.GetBuildResultVirtualPathDependencies(); 
            if (virtualPathDependencies == null)
                continue;

            foreach (string virtualPathDependency in virtualPathDependencies) { 
                BuildProvider dependentBuildProvider = (BuildProvider) _buildProviders[virtualPathDependency];
 
                if (dependentBuildProvider != null) 
                    buildProvider.AddBuildProviderDependency(dependentBuildProvider);
            } 
        }
    }

    // Split the providers into non dependent buckets 
    private void ProcessDependencies() {
        // First phase: compute levels in the dependency tree 
 
        int totaldepth = 0;
        Hashtable depth = new Hashtable(); 
        Stack stack = new Stack();

        // compute depths
        foreach (BuildProvider buildProvider in _buildProviders.Values) { 
            stack.Push(buildProvider);
 
            while (stack.Count > 0) { 
                BuildProvider curnode = (BuildProvider)stack.Peek();
 
                bool recurse = false;
                int maxdepth = 0;

                if (curnode.BuildProviderDependencies != null) { 
                    foreach (BuildProvider child in curnode.BuildProviderDependencies) {
 
                        if (depth.ContainsKey(child)) { 
                            if (maxdepth <= (int)depth[child])
                                maxdepth = (int)depth[child] + 1; 
                            else if ((int)depth[child] == -1)
                                throw new HttpException(SR.GetString(SR.File_Circular_Reference, child.VirtualPath));
                        }
                        else { 
                            recurse = true;
                            stack.Push(child); 
                        } 
                    }
                } 

                if (recurse)
                    depth[curnode] = -1; // being computed;
                else { 
                    stack.Pop();
                    depth[curnode] = maxdepth; 
                    if (totaldepth <= maxdepth) 
                        totaldepth = maxdepth + 1;
                } 
            }
        }

        // drop into buckets by depth 
        _nonDependentBuckets = new ArrayList[totaldepth];
 
        for (IDictionaryEnumerator en = (IDictionaryEnumerator)depth.GetEnumerator(); en.MoveNext();) { 
            int level = (int)en.Value;
 
            if (_nonDependentBuckets[level] == null)
                _nonDependentBuckets[level] = new ArrayList();

            _nonDependentBuckets[level].Add(en.Key); 
        }
 
#if DBG 
        int i = 0;
        foreach (ICollection buildProviders in _nonDependentBuckets) { 
            Debug.Trace("BuildManager", String.Empty);
            Debug.Trace("BuildManager", "Bucket " + i + " contains " + buildProviders.Count + " files");

            foreach (BuildProvider buildProvider in buildProviders) 
                Debug.Trace("BuildManager", buildProvider.VirtualPath);
            i++; 
        } 
#endif
 
    }

    private bool IsBuildProviderSkipable(BuildProvider buildProvider) {
 
        // If another build provider depends on it, we should not skip it
        if (buildProvider.IsDependedOn) return false; 
 
        // No one depends on it (at least in this directory)
 
        // If it's a source file, skip it.  We need to do this for v1 compatibility,
        // since v1 VS projects contain many source files which have already been
        // precompiled into bin, and that should not be compiled dynamically
        if (buildProvider is SourceFileBuildProvider) 
            return true;
 
        // For the same reason, skip resources 
        if (buildProvider is ResXBuildProvider)
            return true; 

        return false;
    }
 
    private bool CompileNonDependentBuildProviders(ICollection buildProviders) {
 
        // Key: CompilerType, Value: AssemblyBuilder 
        IDictionary assemblyBuilders = new Hashtable();
 
        // List of InternalBuildProvider's that don't ask for a specific language
        ArrayList languageFreeBuildProviders = null;

        // AssemblyBuilder used for providers that don't need a specific language 
        AssemblyBuilder defaultAssemblyBuilder = null;
 
        bool hasParserErrors = false; 

        foreach (BuildProvider buildProvider in buildProviders) { 

            if (IsBuildProviderSkipable(buildProvider))
                continue;
 
            // Instruct the internal build providers to continue processing for more parse errors.
            if (!BuildManager.ThrowOnFirstParseError) { 
                InternalBuildProvider provider = buildProvider as InternalBuildProvider; 
                if (provider != null) {
                    provider.ThrowOnFirstParseError = false; 
                }
            }

            CompilerType compilerType = null; 

            // Get the language 
            try { 
                compilerType = BuildProvider.GetCompilerTypeFromBuildProvider(
                    buildProvider); 
            }
            catch (HttpParseException ex) {
                // Ignore the error if we are in that mode.
                if (_ignoreProvidersWithErrors) { 
                    continue;
                } 
 
                hasParserErrors = true;
 
                // Remember the first parse exception
                if (_firstException == null) {
                    _firstException = ex;
                } 

                if (_parserErrors == null) { 
                    _parserErrors = new ParserErrorCollection(); 
                }
 
                _parserErrors.AddRange(ex.ParserErrors);

                continue;
            } 
            catch {
                // Ignore the error if we are in that mode. 
                if (_ignoreProvidersWithErrors) { 
                    continue;
                } 

                throw;
            }
 
            AssemblyBuilder assemblyBuilder = defaultAssemblyBuilder;
 
            // Is it asking for a specific language? 
            if (compilerType == null) {
                // If this provider doesn't need a specific language, and we haven't created 
                // a default builder yet, just keep track of it
                if (defaultAssemblyBuilder == null) {
                    if (languageFreeBuildProviders == null) {
                        languageFreeBuildProviders = new ArrayList(); 
                    }
 
                    languageFreeBuildProviders.Add(buildProvider); 
                    continue;
                } 
            }
            else {
                // Check if we already have an assembly builder of the right type
                assemblyBuilder = (AssemblyBuilder)assemblyBuilders[compilerType]; 
            }
 
            ICollection typeNames = buildProvider.GetGeneratedTypeNames(); 

            // Starts a new assemblyBuilder if the old one already contains another buildprovider 
            // that uses the same type name
            if (assemblyBuilder == null || assemblyBuilder.IsBatchFull ||
                assemblyBuilder.ContainsTypeNames(typeNames)) {
 
                // If the assemblyBuilder is full, compile it.
                if (assemblyBuilder != null) { 
                    CompileAssemblyBuilder(assemblyBuilder); 
                }
 
                AssemblyBuilder newBuilder = compilerType.CreateAssemblyBuilder(
                    _compConfig, _referencedAssemblies);

                assemblyBuilders[compilerType] = newBuilder; 

                // Remember it as the default if we don't already have one, 
                // or if the default is already full, switch the default to the new one. 
                if (defaultAssemblyBuilder == null ||
                    defaultAssemblyBuilder == assemblyBuilder) { 

                    defaultAssemblyBuilder = newBuilder;
                }
 
                assemblyBuilder = newBuilder;
            } 
 
            assemblyBuilder.AddTypeNames(typeNames);
            assemblyBuilder.AddBuildProvider(buildProvider); 
        }

        // Don't try to compile providers, otherwise compile exceptions will be bubbled up,
        // and we lose the parse errors. 
        if (hasParserErrors) {
            return false; 
        } 

        // Handle all the left over language free providers 
        if (languageFreeBuildProviders != null) {

            // Indicates whether the default assembly builder is not a language specific builder.
            bool newDefaultAssemblyBuilder = (defaultAssemblyBuilder == null); 

            // Add language independent providers to the default assembly builder. 
            foreach (BuildProvider languageFreeBuildProvider in languageFreeBuildProviders) { 

                ICollection typeNames = languageFreeBuildProvider.GetGeneratedTypeNames(); 

                // If we don't have a default language assembly builder, get one or
                // starts a new assemblyBuilder if the old one already contains another buildprovider
                // that uses the same type name 
                if (defaultAssemblyBuilder == null || defaultAssemblyBuilder.IsBatchFull ||
                    defaultAssemblyBuilder.ContainsTypeNames(typeNames)) { 
 
                    // If the default assemblyBuilder is full, compile it.
                    if (defaultAssemblyBuilder != null) { 
                        CompileAssemblyBuilder(defaultAssemblyBuilder);
                    }

                    defaultAssemblyBuilder = CompilerType.GetDefaultAssemblyBuilder( 
                        _compConfig, _referencedAssemblies, _vdir.VirtualPathObject /*configPath*/,
                        null /*outputAssemblyName*/); 
 
                    // the default assembly builder needs to be compiled separately.
                    newDefaultAssemblyBuilder = true; 
                }

                defaultAssemblyBuilder.AddTypeNames(typeNames);
                defaultAssemblyBuilder.AddBuildProvider(languageFreeBuildProvider); 
            }
 
            // Only compile the default assembly builder if it's not part of language specific 
            // assembly builder (which will be compiled separately)
            if (newDefaultAssemblyBuilder) { 
                // Compile the default assembly builder.
                CompileAssemblyBuilder(defaultAssemblyBuilder);
            }
        } 

        foreach (AssemblyBuilder assemblyBuilder in assemblyBuilders.Values) { 
            CompileAssemblyBuilder(assemblyBuilder); 
        }
 
        return true;
    }

    private void CompileAssemblyBuilder(AssemblyBuilder builder) { 

        CompilerResults results; 
 
        try {
            results = builder.Compile(); 
        }
        catch (HttpCompileException e) {
            CacheCompileErrors(builder, e.Results);
            throw; 
        }
 
        CacheAssemblyResults(builder, results); 
    }
} 

}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK