Add resx generation back

This commit is contained in:
Pavel Krymets 2016-02-02 12:19:53 -08:00
parent d1672ffb5b
commit 8854869d11
2 changed files with 202 additions and 2 deletions

View File

@ -0,0 +1,177 @@
use namespace="System"
use namespace="System.Collections.Generic"
use namespace="System.IO"
use namespace="System.Linq"
use namespace="System.Text"
use namespace="System.Xml.Linq"
default resxFile=''
@{
var projectDir = Path.GetDirectoryName(resxFile);
var outDirectory = Path.Combine(projectDir, "Properties");
var projectName = Path.GetFileName(projectDir.TrimEnd((char)'/'));
var namedParameterMatcher = new Regex(@"\{([a-z]\w+)\}", RegexOptions.IgnoreCase);
var numberParameterMatcher = new Regex(@"\{(\d+)\}");
var generatingEnvironment = new StringBuilder();
var fileName = Path.GetFileNameWithoutExtension(resxFile);
var resourceStrings = new List<ResourceData>();
var xml = XDocument.Load(resxFile);
foreach (var entry in xml.Descendants("data"))
{
var name = entry.Attribute("name").Value;
var value = entry.Element("value").Value;
bool usingNamedArgs = true;
var match = namedParameterMatcher.Matches(value);
if (match.Count == 0)
{
usingNamedArgs = false;
match = numberParameterMatcher.Matches(value);
}
var arguments = match.Cast<Match>()
.Select(m => m.Groups[1].Value)
.Distinct();
if (!usingNamedArgs)
{
arguments = arguments.OrderBy(Convert.ToInt32);
}
resourceStrings.Add(
new ResourceData
{
Name = name,
Value = value,
Arguments = arguments.ToList(),
UsingNamedArgs = usingNamedArgs
});
}
generatingEnvironment.AppendFormat(
@"// <auto-generated />
namespace {0}
{{
using System.Globalization;
using System.Reflection;
using System.Resources;
internal static class {1}
{{
private static readonly ResourceManager _resourceManager
= new ResourceManager(""{0}.{1}"", typeof({1}).GetTypeInfo().Assembly);
", projectName, fileName);
foreach (var resourceString in resourceStrings)
{
generatingEnvironment.AppendLine();
RenderHeader(generatingEnvironment, resourceString);
RenderProperty(generatingEnvironment, resourceString);
generatingEnvironment.AppendLine();
RenderHeader(generatingEnvironment, resourceString);
RenderFormatMethod(generatingEnvironment, resourceString);
}
generatingEnvironment.Append(@"
private static string GetString(string name, params string[] formatterNames)
{
var value = _resourceManager.GetString(name);
System.Diagnostics.Debug.Assert(value != null);
if (formatterNames != null)
{
for (var i = 0; i < formatterNames.Length; i++)
{
value = value.Replace(""{"" + formatterNames[i] + ""}"", ""{"" + i + ""}"");
}
}
return value;
}
}
}
");
Directory.CreateDirectory(outDirectory);
var outputPath = Path.Combine(outDirectory, fileName + ".Designer.cs");
File.WriteAllText(outputPath, generatingEnvironment.ToString());
}
functions @{
private static void RenderHeader(StringBuilder builder, ResourceData resourceString)
{
builder.Append(" /// <summary>")
.AppendLine();
foreach (var line in resourceString.Value.Split(new[] { '\n' }, StringSplitOptions.None))
{
builder.AppendFormat(" /// {0}", new XText(line))
.AppendLine();
}
builder.Append(" /// </summary>")
.AppendLine();
}
private static void RenderProperty(StringBuilder builder, ResourceData resourceString)
{
builder.AppendFormat(" internal static string {0}", resourceString.Name)
.AppendLine()
.AppendLine(" {")
.AppendFormat(@" get {{ return GetString(""{0}""); }}", resourceString.Name)
.AppendLine()
.AppendLine(" }");
}
private static void RenderFormatMethod(StringBuilder builder, ResourceData resourceString)
{
builder.AppendFormat(" internal static string Format{0}({1})", resourceString.Name, resourceString.Parameters)
.AppendLine()
.AppendLine(" {");
if(resourceString.Arguments.Count > 0)
{
builder.AppendFormat(@" return string.Format(CultureInfo.CurrentCulture, GetString(""{0}""{1}), {2});",
resourceString.Name,
resourceString.UsingNamedArgs ? ", " + resourceString.FormatArguments : null,
resourceString.ArgumentNames);
}
else
{
builder.AppendFormat(@" return GetString(""{0}"");", resourceString.Name);
}
builder.AppendLine()
.AppendLine(" }");
}
private class ResourceData
{
public string Name { get; set; }
public string Value { get; set; }
public List<string> Arguments { get; set; }
public bool UsingNamedArgs { get; set; }
public string FormatArguments
{
get { return string.Join(", ", Arguments.Select(a => "\"" + a + "\"")); }
}
public string ArgumentNames
{
get { return string.Join(", ", Arguments.Select(GetArgName)); }
}
public string Parameters
{
get { return string.Join(", ", Arguments.Select(a => "object " + GetArgName(a))); }
}
public string GetArgName(string name)
{
return UsingNamedArgs ? name : 'p' + name;
}
}
}

View File

@ -181,6 +181,28 @@ default NUGET_FEED = 'https://api.nuget.org/v3/index.json'
#make-roslyn-fast
ngen-roslyn
#resx
@{
var cultures = CultureInfo.GetCultures(CultureTypes.NeutralCultures | CultureTypes.InstalledWin32Cultures | CultureTypes.SpecificCultures);
foreach (var file in Directory.EnumerateFiles(BASE_DIR, "*.resx", SearchOption.AllDirectories))
{
var splitFileName = Path.GetFileNameWithoutExtension(file).Split(new string[] { "." }, StringSplitOptions.None);
if (splitFileName.Length > 1)
{
var localeString = splitFileName.Last();
if (!cultures.Any(c => localeString.Equals(c.Name)))
{
UpdateResx(file);
}
}
else
{
UpdateResx(file);
}
}
}
#--quiet
@{
AddToE("KOREBUILD_BOWER_INSTALL_OPTIONS", "--quiet");
@ -330,10 +352,11 @@ macro name="DotnetTest" projectFile='string' testParallel='bool'
macro name="XunitTest" projectFile='string' testParallel='bool'
xunit-test
macro name='Dnx' command='string' dnxDir='string' dnvmUse='string'
dnx
macro name="DnxTest" projectFile='string' testParallel='bool'
dnx-test
macro name="UpdateResx" resxFile='string'
k-generate-resx