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