Ejemplo n.º 1
0
        public string GetTemplateSourceCode(string name)
        {
            string sourceCode = File.ReadAllText(GetTemplateFileName(name));
            var    host       = T4Generator as ITextTemplatingEngineHost;

            ParsedTemplate pt = ParsedTemplate.FromText(sourceCode, T4Generator);

            if (pt.Errors.HasErrors)
            {
                host.LogErrors(pt.Errors);
                return(null);
            }

            TemplateSettings settings = TemplatingEngine.GetSettings(T4Generator, pt);

            var ccu = TemplatingEngine.GenerateCompileUnit(host, sourceCode, pt, settings);

            var opts = new CodeGeneratorOptions();

            using (var writer = new StringWriter())
            {
                settings.Provider.GenerateCodeFromCompileUnit(ccu, writer, opts);
                return(writer.ToString());
            }
        }
        static void Generate(TemplateGenerator host, ProjectFile file, out string outputFile)
        {
            outputFile = null;

            string content;

            try {
                content = File.ReadAllText(file.FilePath);
            }
            catch (IOException ex) {
                host.Errors.Add(new CompilerError {
                    ErrorText = GettextCatalog.GetString("Could not read input file '{0}':\n{1}", file.FilePath, ex)
                });
                return;
            }

            var pt = ParsedTemplate.FromText(content, host);

            if (pt.Errors.HasErrors)
            {
                host.Errors.AddRange(pt.Errors);
                return;
            }

            var settings = TemplatingEngine.GetSettings(host, pt);

            if (pt.Errors.HasErrors)
            {
                host.Errors.AddRange(pt.Errors);
                return;
            }

            outputFile         = file.FilePath.ChangeExtension(settings.Provider.FileExtension);
            settings.Name      = settings.Provider.CreateValidIdentifier(file.FilePath.FileNameWithoutExtension);
            settings.Namespace = CustomToolService.GetFileNamespace(file, outputFile);
            settings.IncludePreprocessingHelpers = string.IsNullOrEmpty(settings.Inherits);
            settings.IsPreprocessed = true;

            var ccu = TemplatingEngine.GenerateCompileUnit(host, content, pt, settings);

            host.Errors.AddRange(pt.Errors);
            if (pt.Errors.HasErrors)
            {
                return;
            }

            try {
                using (var writer = new StreamWriter(outputFile, false, System.Text.Encoding.UTF8)) {
                    settings.Provider.GenerateCodeFromCompileUnit(ccu, writer, new CodeGeneratorOptions());
                }
            }
            catch (IOException ex) {
                host.Errors.Add(new CompilerError {
                    ErrorText = GettextCatalog.GetString("Could not write output file '{0}':\n{1}", outputFile, ex)
                });
            }
        }
Ejemplo n.º 3
0
        public void DefaultLanguage()
        {
            DummyHost      host     = new DummyHost();
            string         template = @"<#= DateTime.Now #>";
            ParsedTemplate pt       = ParsedTemplate.FromText(template, host);

            Assert.AreEqual(0, host.Errors.Count);
            TemplateSettings settings = TemplatingEngine.GetSettings(host, pt);

            Assert.AreEqual(settings.Language, "C#");
        }
Ejemplo n.º 4
0
        internal static void GenerateCode(ITextTemplatingEngineHost host, string content, string namespac, string name,
                                          TextWriter writer)
        {
            ParsedTemplate pt = ParsedTemplate.FromText(content, host);

            if (pt.Errors.HasErrors)
            {
                host.LogErrors(pt.Errors);
                return;
            }

            TemplateSettings settings = TemplatingEngine.GetSettings(host, pt);

            if (name != null)
            {
                settings.Name = name;
            }
            if (namespac != null)
            {
                settings.Namespace = namespac;
            }
            if (pt.Errors.HasErrors)
            {
                host.LogErrors(pt.Errors);
                return;
            }

            var ccu = TemplatingEngine.GenerateCompileUnit(host, pt, settings);

            if (pt.Errors.HasErrors)
            {
                host.LogErrors(pt.Errors);
                return;
            }

            var opts = new System.CodeDom.Compiler.CodeGeneratorOptions();

            settings.Provider.GenerateCodeFromCompileUnit(ccu, writer, opts);
        }
        string GenerateCode(ITextTemplatingEngineHost host, string content, string name, string generatorNewline)
        {
            ParsedTemplate pt = ParsedTemplate.FromText(content, host);

            if (pt.Errors.HasErrors)
            {
                host.LogErrors(pt.Errors);
                return(null);
            }

            TemplateSettings settings = TemplatingEngine.GetSettings(host, pt);

            if (name != null)
            {
                settings.Name = name;
            }
            if (pt.Errors.HasErrors)
            {
                host.LogErrors(pt.Errors);
                return(null);
            }

            var ccu = TemplatingEngine.GenerateCompileUnit(host, content, pt, settings);

            if (pt.Errors.HasErrors)
            {
                host.LogErrors(pt.Errors);
                return(null);
            }

            var opts = new System.CodeDom.Compiler.CodeGeneratorOptions();

            using (var writer = new System.IO.StringWriter())
            {
                writer.NewLine = generatorNewline;
                settings.Provider.GenerateCodeFromCompileUnit(ccu, writer, opts);
                return(writer.ToString());
            }
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Extracts template source and assembly  references information from T4 template file.
        /// </summary>
        /// <param name="t4templatePath">Path to T4 template.</param>
        /// <param name="references">List of assembly references for Roslyn.</param>
        /// <param name="templateCode">Template source code.</param>
        /// <param name="imports">List of imports (usings) from T4 template.</param>
        /// <returns>Status of method execution.</returns>
        private int PreprocessTemplate(string t4templatePath, out IReadOnlyCollection <MetadataReference> references, out string templateCode, out IReadOnlyList <string> imports)
        {
            references = Array.Empty <MetadataReference>();
            imports    = Array.Empty <string>();

            var generator    = new TemplateGenerator();
            var templateText = File.ReadAllText(t4templatePath);
            var template     = ParsedTemplate.FromText(templateText, generator);

            // parse template by mono.t4
            if (!generator.PreprocessTemplate(null, TEMPLATE_CLASS_NAME, null, templateText, out var language, out var referencesFromTemplate, out templateCode))
            {
                Console.Error.WriteLine("T4 template pre-processing failed:");
                foreach (CompilerError?error in generator.Errors)
                {
                    if (error != null)
                    {
                        Console.Error.WriteLine($"\t{error.FileName} ({error.Line}, {error.Column}): {error.ErrorText}");
                    }
                }

                return(StatusCodes.T4_ERROR);
            }


            // make some basic assertions
            if (language != "C#")
            {
                Console.Error.WriteLine($"T4 template language should be C# but got '{language}'");
                return(StatusCodes.T4_ERROR);
            }

            // prepare references for compilation
            var referencesList = new List <MetadataReference>();

            // normalize assembly pathes
            for (var i = 0; i < referencesFromTemplate.Length; i++)
            {
                referencesFromTemplate[i] = Path.GetFullPath(referencesFromTemplate[i]);
            }

            // imports from T4
            referencesList.AddRange(referencesFromTemplate.Select(file => MetadataReference.CreateFromFile(file)));

            // default linq2db imports
            // current tool (for host class)
            referencesList.Add(MetadataReference.CreateFromFile(typeof(LinqToDBHost).Assembly.Location));
            // linq2db.Tools
            referencesList.Add(MetadataReference.CreateFromFile(typeof(ScaffoldOptions).Assembly.Location));
            // linq2db
            referencesList.Add(MetadataReference.CreateFromFile(typeof(ProviderName).Assembly.Location));

            // reference all current runtime assemblies to not force user to specify a lot of small stuff
            //
            // get path to framework folder
            var fwPath = Path.GetDirectoryName(typeof(object).Assembly.Location) !;

            // reference netstandard + System*
            referencesList.Add(MetadataReference.CreateFromFile(Path.Combine(fwPath, "netstandard.dll")));
            foreach (var asmName in Directory.GetFiles(fwPath, "System*.dll"))
            {
                referencesList.Add(MetadataReference.CreateFromFile(Path.Combine(fwPath, asmName)));
            }

            var usings = new List <string>();

            foreach (var directive in template.Directives)
            {
                if (directive.Name.ToLowerInvariant() == "import")
                {
                    usings.Add(directive.Extract("namespace"));
                }
            }

            references = referencesList;
            imports    = usings;

            // register assembly resolver for loaded template
            RegisterAssemblyResolver(referencesFromTemplate);

            return(StatusCodes.SUCCESS);
        }
Ejemplo n.º 7
0
        internal static OperationResult InstallUpdateTemplates(string csproj, string[] larancaFiles, string[] larnacaFilesPackageIdentities, string targetDir, string outAddedTemplates)
        {
            var templatesRootPath    = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(typeof(TemplateFileManager).Assembly.Location), "templates"));
            var csprojFolder         = Path.GetDirectoryName(Path.GetFullPath(csproj));
            var targetFolderFullPath = Path.GetFullPath(Path.Combine(csprojFolder, targetDir));
            var rellativeTargetPath  = Path.GetRelativePath(csprojFolder, targetFolderFullPath);

            List <TemplateFile> templates = new List <TemplateFile>();

            foreach (var currentTemplate in Directory.EnumerateFiles(templatesRootPath, "*.lca.tt", SearchOption.AllDirectories))
            {
                ETemplateType        templateType        = ETemplateType.undefined;
                ETemplateReplication templateReplication = ETemplateReplication.undefined;
                bool templateError;
                var  fullTemplatePath = Path.GetFullPath(currentTemplate);
                try
                {
                    var templateContent = File.ReadAllText(fullTemplatePath);
                    var generator       = new ToolTemplateGenerator();
                    var pt            = ParsedTemplate.FromText(templateContent, generator);
                    var extractResult = TemplateLarnacaProperties.Extract(pt);
                    if (extractResult.Fail())
                    {
                        templateError = true;
                        Console.Error.WriteLine($"Failed to extract larnaca properties from template {fullTemplatePath}. {extractResult.StatusMessage}");
                    }
                    else
                    {
                        templateError       = false;
                        templateType        = extractResult.Data.Type;
                        templateReplication = extractResult.Data.Replication;
                    }
                }
                catch (Exception ex)
                {
                    templateError = true;
                    Console.Error.WriteLine($"Failed to load template {currentTemplate}: {ex}");
                }

                if (templateError)
                {
                    continue;
                }

                string subPath;
                if (fullTemplatePath.StartsWith(templatesRootPath, StringComparison.OrdinalIgnoreCase))
                {
                    subPath = fullTemplatePath.Substring(templatesRootPath.Length + 1);
                }
                else
                {
                    subPath = Path.GetFileName(currentTemplate);
                }

                string targetRelativePath;
                if (templateReplication == ETemplateReplication.Single)
                {
                    // no need to larnaca package subdir
                    string targetFullPath = Path.Combine(targetFolderFullPath, subPath);
                    targetRelativePath = Path.GetRelativePath(csprojFolder, targetFullPath);
                }
                else
                {
                    targetRelativePath = null;
                }

                bool singleTemplateWritten = false;

                if (templateType == ETemplateType.Analysis)
                {
                    if (templateReplication != ETemplateReplication.Single)
                    {
                        Console.Error.WriteLine($"Invalid template {currentTemplate}, cannot have templateType={templateType} and templateReplication={templateReplication}");
                    }
                    else
                    {
                        templates.Add(new TemplateFile(fullTemplatePath, subPath, targetRelativePath, "none"));
                    }
                }
                else
                {
                    for (int i = 0; i < larancaFiles.Length; i++)
                    {
                        string currentLarnacaFile      = larancaFiles[i];
                        string currentLarnacaPackageId = larnacaFilesPackageIdentities[i];

                        var loadedFile = DeserializedLarancaFile.Load(currentLarnacaFile);

                        if (loadedFile.Fail())
                        {
                            Console.Error.WriteLine($"Failed to load larnaca file ({currentLarnacaFile}): {loadedFile.StatusMessage}");
                        }
                        else
                        {
                            if (loadedFile.Data.DatabaseMeta != null && templateType == ETemplateType.DB)
                            {
                                if (templateReplication == ETemplateReplication.Project)
                                {
                                    var    targetLarnacaPackageSubdir = Path.Combine(targetFolderFullPath, currentLarnacaPackageId);
                                    string targetFullPath             = Path.Combine(targetLarnacaPackageSubdir, subPath);
                                    targetRelativePath = Path.GetRelativePath(csprojFolder, targetFullPath);
                                    templates.Add(new TemplateFile(fullTemplatePath, subPath, targetRelativePath, currentLarnacaPackageId));
                                }
                                else
                                {
                                    if (!singleTemplateWritten)
                                    {
                                        singleTemplateWritten = true;
                                        templates.Add(new TemplateFile(fullTemplatePath, subPath, targetRelativePath, "none"));
                                    }
                                }
                            }
                        }
                    }
                }
            }

            var updateCsprojOp = WriteTemplateFilesToCsproj(csproj, templates);

            if (updateCsprojOp.Fail())
            {
                return(updateCsprojOp);
            }

            foreach (var currentTemplate in templates)
            {
                // todo: check if newer
                if (currentTemplate.TemplateUpdateTemplateMode != ETemplateUpdateTemplateMode.None)
                {
                    var targetPath = Path.GetFullPath(Path.Combine(csprojFolder, currentTemplate.TargetRelativePath));
                    Directory.CreateDirectory(Path.GetDirectoryName(targetPath));
                    File.Copy(currentTemplate.SourceFullPath, targetPath, true);
                }
            }

            if (!string.IsNullOrWhiteSpace(outAddedTemplates))
            {
                Directory.CreateDirectory(Path.GetDirectoryName(outAddedTemplates));
                File.WriteAllText(outAddedTemplates, string.Join(Environment.NewLine, updateCsprojOp.Data.Values.Select(t => t.TargetRelativePath)));
            }

            return(new OperationResult());
        }
Ejemplo n.º 8
0
        private static TemplateGenerationResult GenerateTemplate(
            string templateFile,
            DeserializedLarancaFile larancaFile,
            string folder,
            string collectorTypesAsm,
            string genUtilsAsm,
            string newtonsoftAsm,
            string projFile)
        {
            var    generator = new ToolTemplateGenerator();
            var    inputFile = templateFile;
            string inputContent;

            try
            {
                inputContent = File.ReadAllText(inputFile);
            }
            catch (IOException ex)
            {
                Console.Error.WriteLine("Could not read input file '" + inputFile + "':\n" + ex);
                return(new TemplateGenerationResult()
                {
                    StatusCode = 1
                });
            }

            if (inputContent.Length == 0)
            {
                Console.Error.WriteLine("Input is empty");
                return(new TemplateGenerationResult()
                {
                    StatusCode = 1
                });
            }

            var pt = ParsedTemplate.FromText(inputContent, generator);
            var larnacaPropertiesExtractResult = TemplateLarnacaProperties.Extract(pt);

            if (larnacaPropertiesExtractResult.Fail())
            {
                Console.Error.WriteLine($"Failed to parse larnaca propertsions of template: {templateFile}. {larnacaPropertiesExtractResult.StatusMessage}");
            }
            var settings = TemplatingEngine.GetSettings(generator, pt);

            settings.Log = Console.Out;

            if (pt.Errors.Count > 0)
            {
                foreach (var currentError in pt.Errors)
                {
                    var currentCompilerError = (CompilerError)currentError;
                    if (currentCompilerError.IsWarning)
                    {
                        Console.WriteLine(currentCompilerError.ToString());
                    }
                    else
                    {
                        Console.Error.WriteLine(currentCompilerError.ToString());
                        generator.Errors.Add(currentCompilerError);
                    }
                }
            }

            var outputFile = inputFile;

            if (Path.HasExtension(outputFile))
            {
                var dir = Path.GetDirectoryName(outputFile);
                var fn  = Path.GetFileNameWithoutExtension(outputFile);
                outputFile = Path.Combine(dir, fn + (settings.Extension ?? ".txt"));
            }
            else
            {
                outputFile = outputFile + (settings.Extension ?? ".txt");
            }

            HashSet <string> assemblyNamesToRemove = new HashSet <string>(new[]
            {
                Path.GetFileName(collectorTypesAsm),
                Path.GetFileName(genUtilsAsm),
                Path.GetFileName(newtonsoftAsm),
            }, StringComparer.OrdinalIgnoreCase);

            //fix template assemblies path
            foreach (var x in settings.Assemblies.ToArray())
            {
                if (assemblyNamesToRemove.Contains(Path.GetFileName(x)))
                {
                    settings.Assemblies.Remove(x);
                }
                else
                {
                    settings.Assemblies.Add(FixPath(x, folder));
                }
            }
            settings.Assemblies.Add(collectorTypesAsm);
            settings.Assemblies.Add(genUtilsAsm);
            settings.Assemblies.Add(newtonsoftAsm);

            string outputContent = null;

            if (!generator.Errors.HasErrors)
            {
                var larnacaDirective = pt.Directives.FirstOrDefault(d => d.Name.Equals("larnaca", StringComparison.OrdinalIgnoreCase));
                if (larancaFile?.DatabaseMeta != null)
                {
                    generator.AddParameter(null, null, "dbMeta", larancaFile.DatabaseMeta);
                }
                generator.AddParameter(null, null, "projFile", projFile);

                outputContent = generator.ProcessTemplate(pt, inputFile, inputContent, ref outputFile, settings);
            }

            if (!generator.Errors.HasErrors)
            {
                try
                {
                    if (outputFile.EndsWith(".g.g.cs", StringComparison.OrdinalIgnoreCase))
                    {
                        outputFile = outputFile.Substring(0, outputFile.Length - ".g.g.cs".Length) + ".g.cs";
                    }

                    File.WriteAllText(outputFile, outputContent, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));

                    if (outputFile.EndsWith(".cs", StringComparison.OrdinalIgnoreCase))
                    {
                        if (larnacaPropertiesExtractResult.Data?.DoNotCompile ?? false)
                        {
                            return(new TemplateGenerationResult());
                        }
                        else
                        {
                            return(new TemplateGenerationResult()
                            {
                                CSFileToCompile = outputFile
                            });
                        }
                    }
                    else if (outputFile.EndsWith(".csproj", StringComparison.OrdinalIgnoreCase))
                    {
                        if ((larnacaPropertiesExtractResult.Data?.Type ?? ETemplateType.undefined) == ETemplateType.Analysis)
                        {
                            return(new TemplateGenerationResult()
                            {
                                AnalysisProjectFileToBuild = outputFile
                            });
                        }
                        else
                        {
                            return(new TemplateGenerationResult());
                        }
                    }
                    else
                    {
                        return(new TemplateGenerationResult());
                    }
                }
                catch (IOException ex)
                {
                    Console.Error.WriteLine("Could not write output file '" + outputFile + "':\n" + ex);
                    return(new TemplateGenerationResult()
                    {
                        StatusCode = 1
                    });
                }
            }
            else
            {
                Console.Error.WriteLine(inputFile == null ? "Processing failed." : $"Processing '{inputFile}' failed.");
                return(new TemplateGenerationResult()
                {
                    StatusCode = 1
                });
            }
        }