Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
169 changes: 167 additions & 2 deletions Catglobe.ResXFileCodeGenerator.Tests/GeneratorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,86 @@ public class GeneratorTests
</data>
</root>";

private const string TextWithUnsupportedChar = @"<?xml version=""1.0"" encoding=""utf-8""?>
<root>
<xsd:schema id=""root"" xmlns="""" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:msdata=""urn:schemas-microsoft-com:xml-msdata"">
<xsd:import namespace=""http://www.w3.org/XML/1998/namespace"" />
<xsd:element name=""root"" msdata:IsDataSet=""true"">
<xsd:complexType>
<xsd:choice maxOccurs=""unbounded"">
<xsd:element name=""metadata"">
<xsd:complexType>
<xsd:sequence>
<xsd:element name=""value"" type=""xsd:string"" minOccurs=""0"" />
</xsd:sequence>
<xsd:attribute name=""name"" use=""required"" type=""xsd:string"" />
<xsd:attribute name=""type"" type=""xsd:string"" />
<xsd:attribute name=""mimetype"" type=""xsd:string"" />
<xsd:attribute ref=""xml:space"" />
</xsd:complexType>
</xsd:element>
<xsd:element name=""assembly"">
<xsd:complexType>
<xsd:attribute name=""alias"" type=""xsd:string"" />
<xsd:attribute name=""name"" type=""xsd:string"" />
</xsd:complexType>
</xsd:element>
<xsd:element name=""data"">
<xsd:complexType>
<xsd:sequence>
<xsd:element name=""value"" type=""xsd:string"" minOccurs=""0"" msdata:Ordinal=""1"" />
<xsd:element name=""comment"" type=""xsd:string"" minOccurs=""0"" msdata:Ordinal=""2"" />
</xsd:sequence>
<xsd:attribute name=""name"" type=""xsd:string"" use=""required"" msdata:Ordinal=""1"" />
<xsd:attribute name=""type"" type=""xsd:string"" msdata:Ordinal=""3"" />
<xsd:attribute name=""mimetype"" type=""xsd:string"" msdata:Ordinal=""4"" />
<xsd:attribute ref=""xml:space"" />
</xsd:complexType>
</xsd:element>
<xsd:element name=""resheader"">
<xsd:complexType>
<xsd:sequence>
<xsd:element name=""value"" type=""xsd:string"" minOccurs=""0"" msdata:Ordinal=""1"" />
</xsd:sequence>
<xsd:attribute name=""name"" type=""xsd:string"" use=""required"" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name=""resmimetype"">
<value>text/microsoft-resx</value>
</resheader>
<resheader name=""version"">
<value>2.0</value>
</resheader>
<resheader name=""reader"">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name=""writer"">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name=""CreateDate"" xml:space=""preserve"">
<value>Oldest</value>
</data>
<data name=""CreateDateDescending"" xml:space=""preserve"">
<value>Newest</value>
</data>
<data name=""Sys.Name"" xml:space=""preserve"">
<value>SystemName</value>
</data>
</root>";


private static void Generate(
IGenerator generator,
bool publicClass = true,
bool staticClass = true,
bool partial = false,
bool nullForgivingOperators = false,
bool staticMembers = true
)
)
{
var expected = $@"// ------------------------------------------------------------------------------
// <auto-generated>
Expand Down Expand Up @@ -200,11 +272,96 @@ namespace Resources;
InnerClassName = innerClassName,
InnerClassVisibility = innerClassVisibility,
InnerClassInstanceName = innerClassInstanceName
}
}
);
ErrorsAndWarnings.Should().BeNullOrEmpty();
SourceCode.ReplaceLineEndings().Should().Be(expected.ReplaceLineEndings());
}

private static void GenerateKeys(
IGenerator generator,
bool publicClass = true,
bool staticClass = false,
bool partial = false,
bool nullForgivingOperators = false,
bool staticMembers = true
)
{
var expected = $@"// ------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
// ------------------------------------------------------------------------------
#nullable enable
namespace Resources;
using System.Globalization;
using System.Resources;

{(publicClass ? "public" : "internal")}{(staticClass ? " static" : string.Empty)}{(partial ? " partial" : string.Empty)} class ActivityEntrySortRuleNames
{{
private static ResourceManager? s_resourceManager;
public static ResourceManager ResourceManager => s_resourceManager ??= new ResourceManager(""Catglobe.Web.App_GlobalResources.ActivityEntrySortRuleNames"", typeof(ActivityEntrySortRuleNames).Assembly);
public{(staticMembers ? " static" : string.Empty)} CultureInfo? CultureInfo {{ get; set; }}

/// <summary>
/// Looks up a localized string similar to Oldest.
/// </summary>
public{(staticMembers ? " static" : string.Empty)} string{(nullForgivingOperators ? string.Empty : "?")} CreateDate => ResourceManager.GetString(nameof(CreateDate), CultureInfo){(nullForgivingOperators ? "!" : string.Empty)};

/// <summary>
/// Looks up a localized string similar to Newest.
/// </summary>
public{(staticMembers ? " static" : string.Empty)} string{(nullForgivingOperators ? string.Empty : "?")} CreateDateDescending => ResourceManager.GetString(nameof(CreateDateDescending), CultureInfo){(nullForgivingOperators ? "!" : string.Empty)};

/// <summary>
/// Looks up a localized string similar to SystemName.
/// </summary>
public{(staticMembers ? " static" : string.Empty)} string{(nullForgivingOperators ? string.Empty : "?")} Sys_Name => ResourceManager.GetString(""Sys.Name"", CultureInfo){(nullForgivingOperators ? "!" : string.Empty)};
public{(staticClass ? " static" : string.Empty)} class Keys
{{

/// <summary>
/// Name of resource CreateDate.
/// </summary>
public const string CreateDate = nameof(CreateDate);

/// <summary>
/// Name of resource CreateDateDescending.
/// </summary>
public const string CreateDateDescending = nameof(CreateDateDescending);

/// <summary>
/// Name of resource Sys.Name.
/// </summary>
public const string Sys_Name = ""Sys.Name"";
}}
}}
";
var (_, sourceCode, errorsAndWarnings) = generator.Generate(
options: new FileOptions()
{
LocalNamespace = "Catglobe.Web.App_GlobalResources",
EmbeddedFilename = "Catglobe.Web.App_GlobalResources.ActivityEntrySortRuleNames",
CustomToolNamespace = "Resources",
ClassName = "ActivityEntrySortRuleNames",
PublicClass = publicClass,
NullForgivingOperators = nullForgivingOperators,
GroupedFile = new GroupedAdditionalFile(
mainFile: new AdditionalTextWithHash(new AdditionalTextStub("", TextWithUnsupportedChar), NewGuid()),
subFiles: Array.Empty<AdditionalTextWithHash>()
),
StaticClass = staticClass,
PartialClass = partial,
StaticMembers = staticMembers,
KeyGeneration = true
}
);
errorsAndWarnings.Should().BeNullOrEmpty();
sourceCode.ReplaceLineEndings().Should().Be(expected.ReplaceLineEndings());
}

[Fact]
public void Generate_StringBuilder_Public()
Expand Down Expand Up @@ -573,6 +730,14 @@ public void Generate_StringBuilder_Name_DuplicatedataGivesWarning()
errs[0].Location.GetLineSpan().StartLinePosition.Line.Should().Be(5);
}

[Fact]
public void Generate_StringBuilder_KeyGeneration()
{
var generator = new StringBuilderGenerator();
GenerateKeys(generator);
GenerateKeys(generator, true, nullForgivingOperators: true);
}

[Fact]
public void Generate_StringBuilder_Name_MemberSameAsFileGivesWarning()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
<RepositoryCommit>frombuild</RepositoryCommit>
<ImplicitUsings>enable</ImplicitUsings>
<IsRoslynComponent>true</IsRoslynComponent>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
</PropertyGroup>

<ItemGroup>
Expand Down
14 changes: 12 additions & 2 deletions Catglobe.ResXFileCodeGenerator/FileOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ public readonly record struct FileOptions
public bool UseResManager { get; init; }
public string EmbeddedFilename { get; init; }
public bool IsValid { get; init; }

public bool KeyGeneration { get; init; }

public FileOptions(
GroupedAdditionalFile groupedFile,
AnalyzerConfigOptions options,
Expand Down Expand Up @@ -129,7 +130,16 @@ GlobalOptions globalOptions
}

IsValid = globalOptions.IsValid;
}

KeyGeneration = globalOptions.KeyGeneration;
if (
options.TryGetValue("build_metadata.EmbeddedResource.KeyGeneration", out var keyGenerationSwitch) &&
keyGenerationSwitch is { Length: > 0 }
)
{
KeyGeneration= keyGenerationSwitch.Equals("true", StringComparison.OrdinalIgnoreCase);
}
}

public static FileOptions Select(
GroupedAdditionalFile file,
Expand Down
5 changes: 5 additions & 0 deletions Catglobe.ResXFileCodeGenerator/GlobalOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public sealed record GlobalOptions // this must be a record or implement IEquata
public string ClassNamePostfix { get; }
public bool UseResManager { get; }
public bool IsValid { get; }
public bool KeyGeneration { get; }

public GlobalOptions(AnalyzerConfigOptions options)
{
Expand Down Expand Up @@ -104,6 +105,10 @@ public GlobalOptions(AnalyzerConfigOptions options)
{
UseResManager = true;
}

KeyGeneration = options.TryGetValue("build_property.ResXFileCodeGenerator_KeyGeneration", out var keyGenerationSwitch) &&
keyGenerationSwitch is { Length: > 0 } &&
keyGenerationSwitch.Equals("true", StringComparison.OrdinalIgnoreCase);
}

public static GlobalOptions Select(AnalyzerConfigOptionsProvider provider, CancellationToken token)
Expand Down
Loading