Skip to content

Commit

Permalink
Escape invalid identifiers for file constants
Browse files Browse the repository at this point in the history
  • Loading branch information
PhenX authored and kzu committed Aug 30, 2023
1 parent d3a9854 commit 60a71f4
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 4 deletions.
34 changes: 30 additions & 4 deletions src/ThisAssembly.Constants/Model.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using Microsoft.CodeAnalysis.CSharp;

[DebuggerDisplay("Values = {RootArea.Values.Count}")]
record Model(Area RootArea)
Expand All @@ -16,6 +18,27 @@ record Area(string Name, string Prefix)
{
public List<Area> NestedAreas { get; init; } = new();
public List<Constant> Values { get; init; } = new();

private static string EscapeIdentifier(string identifier)
{
if (string.IsNullOrWhiteSpace(identifier))
{
return "_";
}

var replaced = identifier
.Select(c => SyntaxFacts.IsIdentifierPartCharacter(c) ? c : '_')
.ToArray();

var result = Regex.Replace(new string(replaced), "(_)+", "_");

if (!SyntaxFacts.IsIdentifierStartCharacter(result[0]))
{
result = "_" + result;
}

return result;
}

public static Area Load(List<Constant> constants, string rootArea = "Constants")
{
Expand All @@ -24,15 +47,18 @@ public static Area Load(List<Constant> constants, string rootArea = "Constants")
foreach (var constant in constants)
{
// Splits: ([area].)*[name]
var parts = constant.Name.Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries);
var parts = constant.Name.Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries)
.Select(EscapeIdentifier)
.ToArray();

if (parts.Length <= 1)
{
root.Values.Add(new Constant(constant.Name, constant.Value, constant.Comment));
root.Values.Add(constant with { Name = EscapeIdentifier(constant.Name) });
}
else
{
var area = GetArea(root, parts.Take(parts.Length - 1));
var value = new Constant(parts.Skip(parts.Length - 1).First(), constant.Value, constant.Comment);
var value = constant with { Name = parts.Skip(parts.Length - 1).First() };

area.Values.Add(value);
}
Expand Down Expand Up @@ -74,4 +100,4 @@ static Area GetArea(Area area, IEnumerable<string> areaPath)
}

[DebuggerDisplay("{Name} = {Value}")]
record Constant(string Name, string? Value, string? Comment);
record Constant(string Name, string? Value, string? Comment);
1 change: 1 addition & 0 deletions src/ThisAssembly.Tests/Content/Docs/12. Readme (copy).txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

4 changes: 4 additions & 0 deletions src/ThisAssembly.Tests/Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ public void CanUseConstants()
public void CanUseFileConstants()
=> Assert.Equal(ThisAssembly.Constants.Content.Docs.License, Path.Combine("Content", "Docs", "License.md"));

[Fact]
public void CanUseFileConstantInvalidIdentifier()
=> Assert.Equal(ThisAssembly.Constants.Content.Docs._12._Readme_copy_, Path.Combine("Content", "Docs", "12. Readme (copy).txt"));

[Fact]
public void CanUseFileConstantLinkedFile()
=> Assert.Equal(ThisAssembly.Constants.Included.Readme, Path.Combine("Included", "Readme.txt"));
Expand Down

0 comments on commit 60a71f4

Please sign in to comment.