Skip to content

Commit 5f7d9b9

Browse files
committed
Improve support for invalid identifier characters
This brings parity with the built-in resource generator, which properly converts |, :, ;, < and > to underscores in the generated member names. Fixes #125
1 parent df06941 commit 5f7d9b9

File tree

6 files changed

+31
-21
lines changed

6 files changed

+31
-21
lines changed

src/ThisAssembly.Strings/CSharp.sbntxt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,35 +18,35 @@
1818
/// </summary>
1919
{{ end }}
2020
{{ func render }}
21-
public static partial class {{ $0.Name }}
21+
public static partial class {{ $0.Id }}
2222
{
2323
{{~ for value in $0.Values ~}}
2424
{{~ if!(value.HasFormat) ~}}
2525
{{- summary value ~}}
26-
public static string {{ value.Name }} => Strings.GetResourceManager("{{ $1 }}").GetString("{{ $0.Prefix + value.Name }}");
26+
public static string {{ value.Id }} => Strings.GetResourceManager("{{ $1 }}").GetString("{{ value.Name }}");
2727
{{~ else ~}}
2828
{{~ if value.IsIndexedFormat ~}}
2929
{{- summary value ~}}
30-
public static string {{ value.Name }}(
30+
public static string {{ value.Id }}(
3131
{{- for arg in value.Format -}}
3232
object arg{{~ arg ~}}{{ if !for.last }}, {{ end }}
3333
{{- end -}})
3434
=> string.Format(
3535
CultureInfo.CurrentCulture,
36-
Strings.GetResourceManager("{{ $1 }}").GetString("{{ $0.Prefix + value.Name }}"),
36+
Strings.GetResourceManager("{{ $1 }}").GetString("{{ value.Name }}"),
3737
{{ for arg in value.Format -}}
3838
arg{{- arg -}}{{- if !for.last -}}, {{ end }}{{- end -}});
3939
{{~ else if value.IsNamedFormat ~}}
4040
{{- summary value ~}}
41-
public static string {{ value.Name }}(
41+
public static string {{ value.Id }}(
4242
{{- for arg in value.Format -}}
4343
object {{ arg ~}}{{ if !for.last }}, {{ end }}
4444
{{- end -}})
4545
=> string.Format(
4646
CultureInfo.CurrentCulture,
4747
Strings
4848
.GetResourceManager("{{ $1 }}")
49-
.GetString("{{ $0.Prefix + value.Name }}")
49+
.GetString("{{ value.Name }}")
5050
{{- for arg in value.Format }}
5151
.Replace("{%{{}%}{{ arg }}{%{}}%}", "{%{{}%}{{ for.index }}{%{}}%}"){{- end -}},
5252
{{ for arg in value.Format -}}

src/ThisAssembly.Strings/Model.cs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ record Model(ResourceArea RootArea, string ResourceName)
1515
static class ResourceFile
1616
{
1717
static readonly Regex FormatExpression = new Regex("{(?<name>[^{}]+)}", RegexOptions.Compiled);
18+
internal static readonly Regex NameReplaceExpression = new Regex(@"\||:|;|\>|\<", RegexOptions.Compiled);
1819

1920
public static ResourceArea Load(string fileName, string rootArea)
2021
{
@@ -33,17 +34,18 @@ public static ResourceArea Load(IEnumerable<XElement> data, string rootArea)
3334
{
3435
// Splits: ([resouce area]_)*[resouce name]
3536
var nameAttribute = element.Attribute("name").Value;
37+
var id = NameReplaceExpression.Replace(nameAttribute, "_");
3638
var valueElement = element.Element("value").Value;
3739
var comment = element.Element("comment")?.Value?.Replace("<", "&lt;").Replace(">", "&gt;");
38-
var areaParts = nameAttribute.Split(new[] { "_" }, StringSplitOptions.RemoveEmptyEntries);
40+
var areaParts = id.Split(new[] { "_" }, StringSplitOptions.RemoveEmptyEntries);
3941
if (areaParts.Length <= 1)
4042
{
41-
root.Values.Add(GetValue(nameAttribute, valueElement) with { Comment = comment });
43+
root.Values.Add(GetValue(id, nameAttribute, valueElement) with { Comment = comment });
4244
}
4345
else
4446
{
4547
var area = GetArea(root, areaParts.Take(areaParts.Length - 1));
46-
var value = GetValue(areaParts.Skip(areaParts.Length - 1).First(), valueElement) with { Comment = comment };
48+
var value = GetValue(areaParts.Skip(areaParts.Length - 1).First(), nameAttribute, valueElement) with { Comment = comment };
4749

4850
area.Values.Add(value);
4951
}
@@ -65,13 +67,13 @@ static ResourceArea GetArea(ResourceArea area, IEnumerable<string> areaPath)
6567
var currentArea = area;
6668
foreach (var areaName in areaPath)
6769
{
68-
var existing = currentArea.NestedAreas.FirstOrDefault(a => a.Name == areaName);
70+
var existing = currentArea.NestedAreas.FirstOrDefault(a => a.Id == areaName);
6971
if (existing == null)
7072
{
7173
if (currentArea.Values.Any(v => v.Name == areaName))
7274
throw new ArgumentException(string.Format(
7375
"Area name '{0}' is already in use as a value name under area '{1}'.",
74-
areaName, currentArea.Name));
76+
areaName, currentArea.Id));
7577

7678
existing = new ResourceArea(areaName, currentArea.Prefix + areaName + "_");
7779
currentArea.NestedAreas.Add(existing);
@@ -83,9 +85,9 @@ static ResourceArea GetArea(ResourceArea area, IEnumerable<string> areaPath)
8385
return currentArea;
8486
}
8587

86-
static ResourceValue GetValue(string resourceName, string resourceValue)
88+
static ResourceValue GetValue(string resourceId, string resourceName, string resourceValue)
8789
{
88-
var value = new ResourceValue(resourceName, resourceValue);
90+
var value = new ResourceValue(resourceId, resourceName, resourceValue);
8991

9092
// Parse parameter names
9193
if (FormatExpression.IsMatch(resourceValue))
@@ -101,15 +103,15 @@ static ResourceValue GetValue(string resourceName, string resourceValue)
101103
}
102104
}
103105

104-
[DebuggerDisplay("Name = {Name}, NestedAreas = {NestedAreas.Count}, Values = {Values.Count}")]
105-
record ResourceArea(string Name, string Prefix)
106+
[DebuggerDisplay("Id = {Id}, NestedAreas = {NestedAreas.Count}, Values = {Values.Count}")]
107+
record ResourceArea(string Id, string Prefix)
106108
{
107109
public List<ResourceArea> NestedAreas { get; init; } = new List<ResourceArea>();
108110
public List<ResourceValue> Values { get; init; } = new List<ResourceValue>();
109111
}
110112

111-
[DebuggerDisplay("{Name} = {Value}")]
112-
record ResourceValue(string Name, string? Raw)
113+
[DebuggerDisplay("{Id} = {Value}")]
114+
record ResourceValue(string Id, string Name, string? Raw)
113115
{
114116
public string? Value => Raw?.Replace(Environment.NewLine, "")?.Replace("<", "&lt;")?.Replace(">", "&gt;");
115117
public string? Comment { get; init; }

src/ThisAssembly.Strings/ThisAssembly.Strings.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,5 @@ such as "Hello {name}".
4343
<ItemGroup>
4444
<EmbeddedResource Include="ThisAssembly.Strings.cs" />
4545
</ItemGroup>
46-
46+
4747
</Project>

src/ThisAssembly.Tests/Resources.resx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@
117117
<resheader name="writer">
118118
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
119119
</resheader>
120-
<data name="Foo_Bar_Baz" xml:space="preserve">
120+
<data name="Foo:Bar&gt;Baz" xml:space="preserve">
121121
<value>Value</value>
122122
</data>
123123
<data name="Foo_Hey" xml:space="preserve">

src/ThisAssembly.Tests/Tests.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,21 @@ namespace ThisAssemblyTests
55
{
66
public class Tests
77
{
8+
[Fact]
9+
public void CanReadResourceFile()
10+
=> Assert.NotNull(ResourceFile.Load("Resources.resx", "Strings"));
11+
812
[Fact]
913
public void CanUseConstants()
1014
=> Assert.Equal("Baz", ThisAssembly.Constants.Foo.Bar);
1115

1216
[Fact]
1317
public void CanUseFileConstants()
14-
=> Assert.Equal(Path.Combine("Content", "Docs", "License.md"), ThisAssembly.Constants.Content.Docs.License);
18+
=> Assert.Equal(ThisAssembly.Constants.Content.Docs.License, Path.Combine("Content", "Docs", "License.md"));
1519

1620
[Fact]
1721
public void CanUseFileConstantLinkedFile()
18-
=> Assert.Equal(Path.Combine("Included", "Readme.txt"), ThisAssembly.Constants.Included.Readme);
22+
=> Assert.Equal(ThisAssembly.Constants.Included.Readme, Path.Combine("Included", "Readme.txt"));
1923

2024
[Fact]
2125
public void CanUseMetadata()

src/ThisAssembly.Tests/ThisAssembly.Tests.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@
5454
</FileConstant>
5555
<AssemblyMetadata Include="Foo" Value="Bar" />
5656
</ItemGroup>
57+
58+
<ItemGroup>
59+
<Compile Include="..\ThisAssembly.Strings\Model.cs" Link="Model.cs" />
60+
</ItemGroup>
5761

5862
<Target Name="GetDependencyTargetPaths" Returns="@(TargetPathWithTargetPlatformMoniker)">
5963
<ItemGroup>

0 commit comments

Comments
 (0)