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;
            ICollection typeNames = buildProvider.GetGeneratedTypeNames();

            // Is it asking for a specific language?
            if (compilerType == null) {
                // If this provider doesn't need a specific language, and we haven't yet created
                // a default builder that is capable of building this, just keep track of it                
                if (defaultAssemblyBuilder == null || defaultAssemblyBuilder.IsBatchFull ||
                    defaultAssemblyBuilder.ContainsTypeNames(typeNames)) {
                    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];
            }

            // 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);
            }
        }

        CompileAssemblyBuilderParallel(assemblyBuilders.Values);
        
        return true;
    }
Ejemplo n.º 2
0
    /*
     * Parse the contents of the string, and catch exceptions
     */
    internal void ParseString(string text, VirtualPath virtualPath, Encoding fileEncoding) {

        System.Web.Util.Debug.Trace("Template", "Starting parse at " + DateTime.Now);

        // Save the previous base dirs and line number
        VirtualPath prevVirtualPath = CurrentVirtualPath;
        int prevLineNumber = _lineNumber;

        // Set the new current base dirs and line number
        CurrentVirtualPath = virtualPath;
        _lineNumber = 1;

        // Always ignore the spaces at the beginning of a string
        flags[ignoreNextSpaceString] = true;

        try {
            ParseStringInternal(text, fileEncoding);

            // If there are parser errors caught in the parser
            if (HasParserErrors) {
                ParserError firstError = ParserErrors[0];

                Exception originalException = firstError.Exception;

                // Use the first error as the inner exception if not already caught one.
                if (originalException == null) {
                    originalException = new HttpException(firstError.ErrorText);
                }

                // Make it a HttpParseException with proper info.
                HttpParseException ex = new HttpParseException(firstError.ErrorText,
                    originalException, firstError.VirtualPath, Text, firstError.Line);

                // Add the rest of the errors
                for (int i = 1; i < ParserErrors.Count; i++) {
                    ex.ParserErrors.Add(ParserErrors[i]);
                }

                // throw the new exception
                throw ex;
            }

            // Make sure that if any code calls ProcessError/ProcessException after this point,
            // it throws the error right away, since we won't look at ParserErrors/_firstParseException
            // anymore
            ThrowOnFirstParseError = true;
        }
        catch (Exception e) {
            ErrorFormatter errorFormatter = null;

            PerfCounters.IncrementCounter(AppPerfCounter.ERRORS_PRE_PROCESSING);
            PerfCounters.IncrementCounter(AppPerfCounter.ERRORS_TOTAL);

            // Check if the exception has a formatter
            errorFormatter = HttpException.GetErrorFormatter(e);

            // If it doesn't, throw a parse exception
            if (errorFormatter == null) {

                throw new HttpParseException(e.Message, e,
                    CurrentVirtualPath, text, _lineNumber);
            }
            else {
                // Otherwise, just rethrow it
                throw;
            }
        }
        finally {
            // Restore the previous base dirs and line number
            CurrentVirtualPath = prevVirtualPath;
            _lineNumber = prevLineNumber;
        }

        System.Web.Util.Debug.Trace("Template", "Ending parse at " + DateTime.Now);
    }
    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;
        }
    }