private Assembly generateTemplateLibraryAssembly(string templateFile,
                                                     string templateCode,
                                                     string prefixCode,
                                                     string suffixCode,                                                     
                                                     FileAndLineMatcher fileAndLineMatcher,
                                                     int lineNumberDelta,
                                                     string writer,
                                                     out string templateLibraryCode)
    {
        foreach (Match m in assembliesRegex.Matches(templateCode)) {
            string assemblyName = m.Groups[2].Value;

            Assembly assembly = null;
            try {
        #pragma warning disable 0618
                assembly = Assembly.LoadWithPartialName(assemblyName);
        #pragma warning restore 0618
            } catch {
            }
            if (dependencyPaths != null) {
                if (assembly == null) {
                    string assemblyPath = dependencyPaths.SingleOrDefault(path => path.EndsWith(assemblyName + ".dll"));
                    if (assemblyPath != null) {
                        try {
                            assembly = Assembly.LoadFrom(assemblyPath);
                        } catch { }
                    }
                }
                if (assembly == null) {
                    string assemblyPath = dependencyPaths.SingleOrDefault(path => path.EndsWith(assemblyName + ".exe"));
                    if (assemblyPath != null) {
                        try {
                            assembly = Assembly.LoadFrom(assemblyPath);
                        } catch { }
                    }
                }
            }

            if ((assembly == null) && !String.IsNullOrEmpty(absoluteOutputDir)) {
                try {
                    assembly = Assembly.LoadFrom(Path.Combine(absoluteOutputDir, assemblyName + ".dll"));
                } catch { }

                if (assembly == null) {
                    try {
                        assembly = Assembly.LoadFrom(Path.Combine(absoluteOutputDir, assemblyName + ".exe"));
                    } catch { }
                }
            }

            if (assembly == null) {
                logger.LogError(templateFile, null, "Could not find assembly '" + assemblyName + "'.", 0, 0);
            } else {
                references.Add(assembly.Location);
            }
            lineNumberDelta += m.Groups[1].Value.ToCharArray().Count(c => c == '\n');
            lineNumberDelta += m.Groups[3].Value.ToCharArray().Count(c => c == '\n');
        }
        templateCode = assembliesRegex.Replace(templateCode, string.Empty);

        foreach (Match m in importsRegex.Matches(templateCode)) {
            string @namespace = m.Groups[2].Value;
            prefixCode = "using " + @namespace + ";\r\n" + prefixCode;
            lineNumberDelta -= 1;
            lineNumberDelta += m.Groups[1].Value.ToCharArray().Count(c => c == '\n');
            lineNumberDelta += m.Groups[3].Value.ToCharArray().Count(c => c == '\n');
        }
        templateCode = importsRegex.Replace(templateCode, string.Empty);

        foreach (Match m in importsRegex.Matches(templateCode)) {
            lineNumberDelta += m.Groups[1].Value.ToCharArray().Count(c => c == '\n');
            lineNumberDelta += m.Groups[2].Value.ToCharArray().Count(c => c == '\n');
        }
        templateCode = codeTemplateRegex.Replace(templateCode, string.Empty);

        templateLibraryCode = prefixCode +
            generateTemplateLibraryCode(new StringReader(templateCode), writer) +
            suffixCode;

        CompilerParameters compilerOptions = new CompilerParameters();
        compilerOptions.GenerateInMemory = true;
        compilerOptions.GenerateExecutable = false;
        compilerOptions.IncludeDebugInformation = true;
        compilerOptions.CompilerOptions = "/define:" + conditionalCompilationSymbols;

        foreach (string reference in references) {
            compilerOptions.ReferencedAssemblies.Add(reference);
        }

        CompilerResults results = codeProvider.CompileAssemblyFromSource(compilerOptions, templateLibraryCode);

        foreach (CompilerError error in results.Errors) {
            string file;
            int line;
            fileAndLineMatcher(templateFile, error.Line, out file, out line);
            if (error.IsWarning) {
                logger.LogWarning(file, error.ErrorNumber, error.ErrorText, line + lineNumberDelta + 1, error.Column);
            } else {
                logger.LogError(file, error.ErrorNumber, error.ErrorText, line + lineNumberDelta + 1, error.Column);
            }
        }

        if (results.Errors.Count == 0) {
            return results.CompiledAssembly;
        } else {
            return null;
        }
    }
コード例 #2
0
    private void processTemplateFile(string templateFile,
                                     string templateFileCode,
                                     IEnumerable <string> templateIncludeFiles,
                                     List <string> compileGeneratedFiles,
                                     List <string> embeddedResourceGeneratedFiles)
    {
        int    lineNumberDelta = -1;
        string entryPoint      = null;

        MatchCollection matches = entryPointRegex.Matches(templateFileCode);

        if (matches.Count == 1)
        {
            entryPoint       = matches[0].Groups[2].Value;
            lineNumberDelta += matches[0].Groups[1].Value.ToCharArray().Count(c => c == '\n');
            lineNumberDelta += matches[0].Groups[3].Value.ToCharArray().Count(c => c == '\n');
            templateFileCode = entryPointRegex.Replace(templateFileCode, string.Empty);
        }
        else if (matches.Count == 0)
        {
            logger.LogError(templateFile, null, "The entry point must be specified by using <%@ EntryPoint Statement=\"...\" %>", 0, 0);
            return;
        }
        else
        {
            logger.LogError(templateFile, null, "Only one entry point can be defined per file.", 0, 0);
            return;
        }

        List <int>    fileStarts = new List <int>();
        List <int>    fileEnds   = new List <int>();
        List <string> fileNames  = new List <string>();

        fileStarts.Add(0);
        fileEnds.Add(templateFileCode.ToCharArray().Count(c => c == '\n'));
        fileNames.Add(templateFile);

        var includeMatches = includesRegex.Matches(templateFileCode);

        templateFileCode = includesRegex.Replace(templateFileCode, string.Empty);
        foreach (Match m in includeMatches)
        {
            var    pathGroup = m.Groups[2];
            string path      = pathGroup.Value.Replace("\\\\", "\\");
            if (!templateIncludeFiles.Contains(path))
            {
                logger.LogWarning(path, null, "Build Action should be set to PreSharpTemplateInclude", 0, 0);
            }
            lineNumberDelta += m.Groups[1].Value.ToCharArray().Count(c => c == '\n');
            lineNumberDelta += m.Groups[3].Value.ToCharArray().Count(c => c == '\n');
            string includedFile = File.ReadAllText(path);
            templateFileCode += includedFile;
            int previous = fileEnds.Last() + 1;
            fileStarts.Add(previous);
            fileEnds.Add(previous + includedFile.ToCharArray().Count(c => c == '\n'));
            fileNames.Add(path);
        }

        FileAndLineMatcher fileAndLineMatcher = delegate(string originalFile, int originalLine, out string file, out int line) {
            file = originalFile;
            line = originalLine;
            for (int i = 0; i < fileEnds.Count; ++i)
            {
                if (originalLine >= fileStarts[i] && originalLine <= fileEnds[i])
                {
                    file = fileNames[i];
                    line = originalLine - fileStarts[i];
                }
            }
        };

        string generatedClassName = "GeneratedClass_" + Guid.NewGuid().ToString("N");
        string suffix             = "\r\n" +
                                    "\r\n" +
                                    "internal static class " + generatedClassName + " {\r\n" +
                                    "\r\n" +
                                    "    private static void DumpOutput() {\r\n" +
                                    "        " + entryPoint + "\r\n" +
                                    "    }\r\n" +
                                    "}\r\n";

        templateFileCode = templateFileCode.Replace("#if PRESHARP_TEMPLATE\r\n", "\r\n%>");
        templateFileCode = templateFileCode.Replace("#if PRESHARP_TEMPLATE\n", "\n%>");
        templateFileCode = templateFileCode.Replace("\r\n#endif", "<%\r\n");
        templateFileCode = templateFileCode.Replace("\n#endif", "<%\n");
        templateFileCode = templateFileCode.Replace("#endif", "<%");

        try {
            string   templateLibraryCode;
            Assembly generatedAssembly = generateTemplateLibraryAssembly(templateFile,
                                                                         "<%" + templateFileCode + "%>",
                                                                         string.Empty,
                                                                         suffix,
                                                                         fileAndLineMatcher,
                                                                         lineNumberDelta,
                                                                         "PreSharp.Writer",
                                                                         out templateLibraryCode);

            string processedTemplateFile = templateFile + ".PreSharpDebug.cs";
            File.WriteAllText(processedTemplateFile, templateLibraryCode);
            logger.LogMessage("Generated debug file '" + processedTemplateFile + "'.");

            if (generatedAssembly == null)
            {
                return;
            }

            try {
                Type generatedClassType = generatedAssembly.GetType(generatedClassName);
                generatedClassType.GetMethod("DumpOutput", BindingFlags.Static | BindingFlags.NonPublic).Invoke(null, null);

                if (!PreSharp.HasOutputs)
                {
                    logger.LogError(templateFile, null, "At least one template output must be specified by using PreSharp.SetOutput(string outputFile, PreSharp.OutputType outputType)", 0, 0);
                }
                else
                {
                    List <string> compileGeneratedFilesFromThisTemplate          = PreSharp.CompileGeneratedFiles;
                    List <string> embeddedResourceGeneratedFilesFromThisTemplate = PreSharp.EmbeddedResourceGeneratedFiles;

                    foreach (string compileGeneratedFile in compileGeneratedFilesFromThisTemplate)
                    {
                        logger.LogMessage("Generated file '" + compileGeneratedFile + "' from template '" + templateFile + "'.");
                        compileGeneratedFiles.Add(compileGeneratedFile);
                    }
                    foreach (string embeddedResourceGeneratedFile in embeddedResourceGeneratedFilesFromThisTemplate)
                    {
                        logger.LogMessage("Generated file '" + embeddedResourceGeneratedFile + "' from template '" + templateFile + "'.");
                        embeddedResourceGeneratedFiles.Add(embeddedResourceGeneratedFile);
                    }
                }
            } finally {
                PreSharp.Flush();
                PreSharp.CompileGeneratedFiles.Clear();
                PreSharp.EmbeddedResourceGeneratedFiles.Clear();
            }
        } catch (TargetInvocationException exception) {
            logger.LogException(templateFile, exception.InnerException);
        } catch (Exception exception) {
            logger.LogException(templateFile, exception);
        }
    }
コード例 #3
0
    private Assembly generateTemplateLibraryAssembly(string templateFile,
                                                     string templateCode,
                                                     string prefixCode,
                                                     string suffixCode,
                                                     FileAndLineMatcher fileAndLineMatcher,
                                                     int lineNumberDelta,
                                                     string writer,
                                                     out string templateLibraryCode)
    {
        foreach (Match m in assembliesRegex.Matches(templateCode))
        {
            string assemblyName = m.Groups[2].Value;

            Assembly assembly = null;
            try {
#pragma warning disable 0618
                assembly = Assembly.LoadWithPartialName(assemblyName);
#pragma warning restore 0618
            } catch {
            }
            if (dependencyPaths != null)
            {
                if (assembly == null)
                {
                    string assemblyPath = dependencyPaths.SingleOrDefault(path => path.EndsWith(assemblyName + ".dll"));
                    if (assemblyPath != null)
                    {
                        try {
                            assembly = Assembly.LoadFrom(assemblyPath);
                        } catch { }
                    }
                }
                if (assembly == null)
                {
                    string assemblyPath = dependencyPaths.SingleOrDefault(path => path.EndsWith(assemblyName + ".exe"));
                    if (assemblyPath != null)
                    {
                        try {
                            assembly = Assembly.LoadFrom(assemblyPath);
                        } catch { }
                    }
                }
            }

            if ((assembly == null) && !String.IsNullOrEmpty(absoluteOutputDir))
            {
                try {
                    assembly = Assembly.LoadFrom(Path.Combine(absoluteOutputDir, assemblyName + ".dll"));
                } catch { }

                if (assembly == null)
                {
                    try {
                        assembly = Assembly.LoadFrom(Path.Combine(absoluteOutputDir, assemblyName + ".exe"));
                    } catch { }
                }
            }

            if (assembly == null)
            {
                logger.LogError(templateFile, null, "Could not find assembly '" + assemblyName + "'.", 0, 0);
            }
            else
            {
                references.Add(assembly.Location);
            }
            lineNumberDelta += m.Groups[1].Value.ToCharArray().Count(c => c == '\n');
            lineNumberDelta += m.Groups[3].Value.ToCharArray().Count(c => c == '\n');
        }
        templateCode = assembliesRegex.Replace(templateCode, string.Empty);

        foreach (Match m in importsRegex.Matches(templateCode))
        {
            string @namespace = m.Groups[2].Value;
            prefixCode       = "using " + @namespace + ";\r\n" + prefixCode;
            lineNumberDelta -= 1;
            lineNumberDelta += m.Groups[1].Value.ToCharArray().Count(c => c == '\n');
            lineNumberDelta += m.Groups[3].Value.ToCharArray().Count(c => c == '\n');
        }
        templateCode = importsRegex.Replace(templateCode, string.Empty);

        foreach (Match m in importsRegex.Matches(templateCode))
        {
            lineNumberDelta += m.Groups[1].Value.ToCharArray().Count(c => c == '\n');
            lineNumberDelta += m.Groups[2].Value.ToCharArray().Count(c => c == '\n');
        }
        templateCode = codeTemplateRegex.Replace(templateCode, string.Empty);

        templateLibraryCode = prefixCode +
                              generateTemplateLibraryCode(new StringReader(templateCode), writer) +
                              suffixCode;


        CompilerParameters compilerOptions = new CompilerParameters();
        compilerOptions.GenerateInMemory        = true;
        compilerOptions.GenerateExecutable      = false;
        compilerOptions.IncludeDebugInformation = true;
        compilerOptions.CompilerOptions         = "/define:" + conditionalCompilationSymbols;

        foreach (string reference in references)
        {
            compilerOptions.ReferencedAssemblies.Add(reference);
        }

        CompilerResults results = codeProvider.CompileAssemblyFromSource(compilerOptions, templateLibraryCode);

        foreach (CompilerError error in results.Errors)
        {
            string file;
            int    line;
            fileAndLineMatcher(templateFile, error.Line, out file, out line);
            if (error.IsWarning)
            {
                logger.LogWarning(file, error.ErrorNumber, error.ErrorText, line + lineNumberDelta + 1, error.Column);
            }
            else
            {
                logger.LogError(file, error.ErrorNumber, error.ErrorText, line + lineNumberDelta + 1, error.Column);
            }
        }

        if (results.Errors.Count == 0)
        {
            return(results.CompiledAssembly);
        }
        else
        {
            return(null);
        }
    }