What's wrong
ToUppercaseFirstChar and ToLowercaseFirstChar (CaseConverter/CaseConverter.cs ~L129–155) change the case of input[0] first, and only then call CollapseSpaces(...).Trim():
return CollapseSpaces(char.ToUpperInvariant(input[0]) + input[1..]).Trim();
If the string starts with whitespace, the whitespace is what gets case-mapped. The trim then removes it, and the first letter is returned unchanged. Both methods also collapse runs of internal spaces, which their summaries ("with the first character converted…") don't mention.
Failure scenario (reproduced)
" hello".ToUppercaseFirstChar() → "hello" (expected "Hello")
"\thello".ToUppercaseFirstChar() → "hello"
" Hello".ToLowercaseFirstChar() → "Hello" (expected "hello")
"a b".ToUppercaseFirstChar() → "A b" (internal spacing changed without saying so)
The caller does get a trimmed string back, so the result looks processed, but the case change never happened.
This is not covered by #74 (first letters outside the BMP). The open PR for #74 rewrites these methods around MapFirstCodePoint, but it keeps the map-then-trim order, so this bug is still there after that PR.
Suggested fix
Trim, or skip leading whitespace, before mapping the first code point. Then either remove CollapseSpaces from these two public helpers or document it in their XML summaries.
Acceptance criteria
" hello".ToUppercaseFirstChar() == "Hello" and " Hello".ToLowercaseFirstChar() == "hello", with tests.
- The internal-space behaviour is either kept and documented, or removed and tested.
What's wrong
ToUppercaseFirstCharandToLowercaseFirstChar(CaseConverter/CaseConverter.cs~L129–155) change the case ofinput[0]first, and only then callCollapseSpaces(...).Trim():If the string starts with whitespace, the whitespace is what gets case-mapped. The trim then removes it, and the first letter is returned unchanged. Both methods also collapse runs of internal spaces, which their summaries ("with the first character converted…") don't mention.
Failure scenario (reproduced)
" hello".ToUppercaseFirstChar()→"hello"(expected"Hello")"\thello".ToUppercaseFirstChar()→"hello"" Hello".ToLowercaseFirstChar()→"Hello"(expected"hello")"a b".ToUppercaseFirstChar()→"A b"(internal spacing changed without saying so)The caller does get a trimmed string back, so the result looks processed, but the case change never happened.
This is not covered by #74 (first letters outside the BMP). The open PR for #74 rewrites these methods around
MapFirstCodePoint, but it keeps the map-then-trim order, so this bug is still there after that PR.Suggested fix
Trim, or skip leading whitespace, before mapping the first code point. Then either remove
CollapseSpacesfrom these two public helpers or document it in their XML summaries.Acceptance criteria
" hello".ToUppercaseFirstChar() == "Hello"and" Hello".ToLowercaseFirstChar() == "hello", with tests.