From 076ab987b114986d04fa62a7d3f0bb9eca0a3d23 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 12 Feb 2014 05:56:28 -0800 Subject: [PATCH] Changing resx generation to use tt file --- build/Resources.tt | 138 +++++++++++++++++++++++++++++++ build/_k-generate-projects.shade | 18 ++-- 2 files changed, 150 insertions(+), 6 deletions(-) create mode 100644 build/Resources.tt diff --git a/build/Resources.tt b/build/Resources.tt new file mode 100644 index 0000000000..57503ce8da --- /dev/null +++ b/build/Resources.tt @@ -0,0 +1,138 @@ +<#@ template debug="true" hostspecific="true" language="C#" #> +<#@ assembly name="System.Core" #> +<#@ assembly name="System.Windows.Forms" #> +<#@ assembly name="Microsoft.VisualStudio.Shell.Interop.8.0" #> +<#@ assembly name="EnvDTE" #> +<#@ assembly name="EnvDTE80" #> +<#@ import namespace="System" #> +<#@ import namespace="System.Collections" #> +<#@ import namespace="System.Collections.Generic" #> +<#@ import namespace="System.IO" #> +<#@ import namespace="System.Linq" #> +<#@ import namespace="System.Resources" #> +<#@ import namespace="System.Text" #> +<#@ import namespace="System.Text.RegularExpressions" #> +<#@ import namespace="Microsoft.VisualStudio.Shell.Interop" #> +<#@ import namespace="EnvDTE" #> +<#@ import namespace="EnvDTE80" #> + +<# + var hostServiceProvider = (IServiceProvider)Host; + var dte = (EnvDTE.DTE)hostServiceProvider.GetService(typeof(EnvDTE.DTE)); + var templateProjectItem = dte.Solution.FindProjectItem(Host.TemplateFile); + + var projectDirectory = Path.GetDirectoryName(templateProjectItem.ContainingProject.FullName); + var ttDirectory = Path.Combine(projectDirectory, "Properties"); + var projectName = Path.GetFileName(projectDirectory.TrimEnd('/')); + + foreach (var resxFile in Directory.EnumerateFiles(projectDirectory, "*.resx", SearchOption.AllDirectories)) + { + var fileName = Path.GetFileNameWithoutExtension(resxFile); + var parameterMatcher = new Regex(@"\{(\d)\}"); + var resourceStrings = new List(); + + using (var resxReader = new ResXResourceReader(resxFile)) + { + resxReader.UseResXDataNodes = true; + + foreach (DictionaryEntry entry in resxReader) + { + var node = (ResXDataNode)entry.Value; + var value = (string)node.GetValue((System.ComponentModel.Design.ITypeResolutionService)null); + + var matchedArgs + = parameterMatcher.Matches(value) + .Cast() + .Select(m => Convert.ToInt32(m.Groups[1].Value)) + .ToArray(); + + resourceStrings.Add(new ResourceData { + Name = node.Name, + Value = value, + ArgsCount = matchedArgs.Any() ? matchedArgs.Max() + 1 : 0 + }); + } + } + string outputNamespace = Host.ResolveParameterValue("directiveId", "namespaceDirectiveProcessor", "namespaceHint") ?? projectName; +#> +// + +namespace <#= outputNamespace #> +{ + using System.Globalization; + using System.Reflection; + using System.Resources; + + internal static class <#= fileName #> + { + private static readonly ResourceManager _resourceManager + = new ResourceManager("<#= projectName + "." + fileName #>", typeof(<#= fileName #>).GetTypeInfo().Assembly); +<# + foreach (var resourceString in resourceStrings) + { + #> + + /// +<# foreach (var line in resourceString.Value.Split(new[] { Environment.NewLine }, StringSplitOptions.None)) { #> + /// <#= line.Replace("<", "<").Replace(">", ">") #> +<# } #> + /// + internal static string <#= resourceString.Name #><#= resourceString.ArgsCount > 0 ? resourceString.ParamsArray : string.Empty #> + { + <# + if (resourceString.ArgsCount == 0) + { + #>get { return GetString("<#= resourceString.Name #>"); } +<# + } + else + { + #>return string.Format(CultureInfo.CurrentCulture, GetString("<#= resourceString.Name #>"), <#= resourceString.ArgsArray #>); +<# + }#> + } +<# + }#> + + private static string GetString(string name) + { + string value = _resourceManager.GetString(name); + System.Diagnostics.Debug.Assert(value != null); + return value; + } + } +} +<# + string outputPath = Path.Combine(ttDirectory, fileName + ".Designer.cs"); + bool fileExists = File.Exists(outputPath); + File.WriteAllText(outputPath, GenerationEnvironment.ToString()); + GenerationEnvironment.Length = 0; + if (!fileExists) { + + templateProjectItem.ProjectItems.AddFromFile(outputPath); + } +} +#> +<#+ + private class ResourceData + { + public string Name { get; set; } + public string Value { get; set; } + public int ArgsCount { get; set; } + + public string ArgsArray + { + get { return GenerateArgs("p"); } + } + + public string ParamsArray + { + get { return "(" + GenerateArgs("object p") + ")"; } + } + + private string GenerateArgs(string template) + { + return string.Join(", ", Enumerable.Range(0, ArgsCount).Select(i => template + i)); + } + } +#> \ No newline at end of file diff --git a/build/_k-generate-projects.shade b/build/_k-generate-projects.shade index 7dfa97f9d7..761a632e75 100644 --- a/build/_k-generate-projects.shade +++ b/build/_k-generate-projects.shade @@ -207,16 +207,13 @@ functions // Templates const string csTemplate = @""; const string resxDesignerTemplate = @" - {1} + Resources.tt True True "; const string resxTemplate = @" {1}.{2}.resources - ResXFileCodeGenerator - {2}.Designer.cs - {1}.Resources -"; + "; // Build the list of resx files var resxFileNames = FindFilesOfType(projectDir, "*.resx"); @@ -230,7 +227,7 @@ functions var csFiles = String.Join(Environment.NewLine, FindFilesOfType(projectDir, "*.cs") - .Select(p => resxDesignerFiles.Contains(p) ? String.Format(resxDesignerTemplate, p, Path.ChangeExtension(Path.GetFileNameWithoutExtension(p), "resx")) : + .Select(p => resxDesignerFiles.Contains(p) ? String.Format(resxDesignerTemplate, p) : String.Format(csTemplate, p))); bool isSample = Path.GetDirectoryName(projectDir) @@ -252,6 +249,15 @@ functions // HACK: Assume the packages folder is 2 up from the projectDir string packagesDir = Path.GetFullPath(Path.Combine(projectDir, "..", "..", "packages")); + + string ttFileTemplate = @" + Properties\Resources.tt + TextTemplatingFileGenerator + _Resources.cs + {0} +"; + // Link the tt file from packages dir + resxFiles += Environment.NewLine + String.Format(ttFileTemplate, projectName); foreach (var pair in configs) {