示例#1
0
        private Assembly CompileCode(List <GeneratedCode> generatedCodes)
        {
            // Prepare compiler
            var parameters = new CompilerParameters();

            parameters.GenerateInMemory        = true;
            parameters.TreatWarningsAsErrors   = true;
            parameters.IncludeDebugInformation = true;
            parameters.CompilerOptions         = string.Join(" ", Constants.CompilerOptions);
            parameters.ReferencedAssemblies.AddRange(Constants.CompilerAssemblies);
            parameters.ReferencedAssemblies.AddRange(this.ReferencedAssemblies.ToArray());
            parameters.ReferencedAssemblies.Add(typeof(TemplateCompiler).Assembly.Location);

            // Compile
            CompilerResults compilerResults;

            using (var codeProvider = new CSharpCodeProvider())
            {
                var codes = generatedCodes.Select(generatedCode => generatedCode.Code).ToArray();
                compilerResults = codeProvider.CompileAssemblyFromSource(parameters, codes);
            }

            // Report errors
            foreach (CompilerError compilerError in compilerResults.Errors)
            {
                string filename     = compilerError.FileName;
                var    textPosition = new TextPosition();
                if (compilerError.Line != 0 && compilerError.Column != 0)
                {
                    GeneratedCode generatedCode = generatedCodes.FirstOrDefault(gcode => string.Compare(gcode.TemplatePath, compilerError.FileName, StringComparison.OrdinalIgnoreCase) == 0);
                    if (generatedCode != null)
                    {
                        var errorPosition         = new TextPosition(compilerError.Line, compilerError.Column);
                        TextFilePosition original = generatedCode.SourceMap.FindSourceByGenerated(errorPosition);
                        if (original.IsValid)
                        {
                            textPosition = new TextPosition(original.Line, original.Column);
                        }
                    }
                    else
                    {
                        textPosition = new TextPosition(compilerError.Line, compilerError.Column);
                    }
                }

                TraceLevel traceLevel = compilerError.IsWarning ? TraceLevel.Warning : TraceLevel.Error;
                this.MessageHandler.Message(traceLevel, $"{compilerError.ErrorNumber}: {compilerError.ErrorText}", filename, textPosition);
            }

            if (compilerResults.Errors.Count > 0)
            {
                return(null);
            }
            return(compilerResults.CompiledAssembly);
        }
示例#2
0
        /// <summary>
        /// Loads the given template and compiles it.
        /// </summary>
        /// <param name="templateName">Name of template which will be resolved by ITemplateLoader.</param>
        /// <returns>Compiled template or null in case of an error.</returns>
        /// <exception cref="ArgumentException">If templateName is null or empty.</exception>
        public CompiledTemplate Compile(string templateName)
        {
            if (string.IsNullOrEmpty(templateName))
            {
                throw new ArgumentException("Can't be null or empty.", nameof(templateName));
            }

            var templateNames = new Queue <string>();

            templateNames.Enqueue(templateName);

            var generatedTargetCodes = new List <GeneratedCode>();

            string mainTemplatePath        = null;
            bool   mainTemplateFilenameSet = false;
            var    generatedFiles          = new HashSet <string>();

            while (templateNames.Count > 0)
            {
                // Load template
                string   loadTemplateName = templateNames.Dequeue();
                Template template         = null;
                try
                {
                    template = this.TemplateLoader.Load(loadTemplateName);
                    if (mainTemplateFilenameSet == false)
                    {
                        mainTemplatePath        = template.Path;
                        mainTemplateFilenameSet = true;
                    }
                }
                catch (FileNotFoundException)
                {
                    this.MessageHandler.Message(TraceLevel.Error, $"Can't find template '{templateName}'.", string.Empty, new TextPosition());
                    throw;
                }
                catch (IOException)
                {
                    this.MessageHandler.Message(TraceLevel.Error, $"IO error while reading template '{templateName}'.", string.Empty, new TextPosition());
                    throw;
                }
                catch (Exception)
                {
                    continue;
                }

                // Generate Twofold enhanced CSharp code from template
                List <string> includedFiles;
                GeneratedCode generatedCode = this.GenerateCode(template.Path, template.Text, out includedFiles);
                if (generatedCode != null)
                {
                    generatedFiles.Add(loadTemplateName);
                    generatedTargetCodes.Add(generatedCode);
                    foreach (var includedFile in includedFiles)
                    {
                        if (generatedFiles.Contains(includedFile))
                        {
                            continue;
                        }
                        templateNames.Enqueue(includedFile);
                    }
                }
            }

            // Compile CSharp code
            Assembly assembly = this.CompileCode(generatedTargetCodes);

            if (assembly == null)
            {
                return(new CompiledTemplate(mainTemplatePath, generatedTargetCodes));
            }

            // Check Twofold CSharp assembly for entry points/types
            string mainTypeName = this.DetectMainType(mainTemplatePath, assembly);

            if (string.IsNullOrEmpty(mainTypeName))
            {
                return(new CompiledTemplate(mainTemplatePath, generatedTargetCodes));
            }

            return(new CompiledTemplate(mainTemplatePath, assembly, mainTypeName, generatedTargetCodes));
        }