Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Oct 23, 2025

Problem

The MemberNameStrategies.SnakeCase strategy had a bug when converting property names containing consecutive uppercase letters (acronyms). This caused templates to fail to render values for such properties.

For example, consider this code:

var options = new TemplateOptions();
options.MemberAccessStrategy.MemberNameStrategy = MemberNameStrategies.SnakeCase;

var model = new { ID = 12345 };
var context = new TemplateContext(model, options);

if (new FluidParser().TryParse("{{ id }}", out var template, out var error))
{
    Console.WriteLine(template.Render(context)); // Outputs nothing (empty string)
}

The issue affected any property name with consecutive uppercase letters followed by lowercase letters:

  • OpenAIModel was incorrectly converted to open_aimodel instead of open_ai_model
  • OEMVendor was incorrectly converted to oemvendor instead of oem_vendor
  • IDSecurity was incorrectly converted to idsecurity instead of id_security
  • ID produced an invalid string with a null character

Root Cause

The algorithm didn't handle the case where consecutive uppercase letters are followed by a lowercase letter. When this pattern occurs (e.g., "AI" in "OpenAIModel"), the last uppercase letter ("I") actually starts a new word ("Model") and should have an underscore before it.

Additionally, the NET6+ implementation had a buffer size calculation bug where it pre-allocated space based on the total number of uppercase letters, but the actual logic didn't always need that many underscores, leading to uninitialized characters in the output.

Solution

Updated both the NET6+ and pre-NET6 implementations of RenameSnakeCase to:

  1. Correctly detect word boundaries: Insert an underscore before an uppercase letter when:

    • It's not at the start of the string (i > 0), AND
    • Either the previous character was lowercase (standard camelCase transition)
    • OR the previous character was uppercase AND the next character is lowercase (end of acronym)
  2. Fix buffer sizing: Calculate the exact number of underscores needed upfront to ensure the output string is properly sized

Changes

  • Fixed MemberNameStrategies.RenameSnakeCase for NET6+ (.NET 6.0 and later)
  • Fixed MemberNameStrategies.RenameSnakeCase for pre-NET6 frameworks
  • Added comprehensive test coverage for acronym handling

Verified Conversions

All conversions now work correctly:

  • UserNameuser_name
  • OpenAIModelopen_ai_model
  • OEMVendoroem_vendor
  • IDSecurityid_security
  • IDid
  • XMLParserxml_parser
  • HTMLElementhtml_element
  • IOErrorio_error
  • JSONDatajson_data

The fix works correctly in both modern mode (using System.Text.Json naming policies) and legacy mode (using custom implementation).

Fixes #1234

Original prompt

This section details on the original issue you should resolve

<issue_title>MemberNameStrategies. SnakeCase strategy use uppercase attribute has a bug</issue_title>
<issue_description>```
var options = new TemplateOptions();

options.MemberAccessStrategy.MemberNameStrategy = MemberNameStrategies.SnakeCase;
var model = new { ID = 12345 };
var context = new TemplateContext(model,options);

if (new FluidParser().TryParse("{{ id }}", out IFluidTemplate? template, out var error))
{
Console.WriteLine(template.Render(context));
}


The console has no output</issue_description>

<agent_instructions>Ensure that these conversions are correct after the fix:

UserName
user_name
OpenAIModel
OEMVendor
IDSecurity
ID


are converted to 

user_name
user_name
open_ai_model
oem_vendor
id_security
id


## Comments on the Issue (you are @copilot in this section)

<comments>
<comment_new><author>@hishamco</author><body>
The 'id' is not a snake case, but of course a bug. Could you try 'user_name` for instance</body></comment_new>
</comments>

Fixes #616


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI changed the title [WIP] Fix SnakeCase strategy bug for member names Fix SnakeCase conversion for properties with consecutive uppercase letters Oct 23, 2025
Copilot AI requested a review from sebastienros October 23, 2025 15:52
@sebastienros sebastienros marked this pull request as ready for review October 23, 2025 15:55
@sebastienros sebastienros enabled auto-merge (squash) October 23, 2025 15:55
@sebastienros sebastienros merged commit 4d9e15c into main Oct 23, 2025
6 checks passed
@sebastienros sebastienros deleted the copilot/fix-snake-case-bug branch October 23, 2025 16:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MemberNameStrategies. SnakeCase strategy use uppercase attribute has a bug

2 participants