Skip to content

Commit 762a0d6

Browse files
author
mforce
committed
fix(#417): codex round 99 — full C# identifier categories in type scan
IsLetterOrDigit misses identifier continuation characters the language permits as LITERALS — letter numbers, connector punctuation, combining marks, and format characters — so a tuple element name carrying a decomposed combining mark stopped TryConsumeTypeParen and left the hole identifier-led while the interpolated null bridged the fragments. IsCSharpIdentifierChar now implements the language's identifier-part categories and replaces IsLetterOrDigit in the type scanner's whitelist. The atom checks' keyword walk deliberately keeps the narrow class: keywords are pure ASCII and an escape- or combining-spelled lookalike is an IDENTIFIER by the spec, so passing it as identifier-led is correct, not a gap. Mutation-verified: a tuple element name with a literal decomposed combining mark (byte-verified present in the injected file) and one with connector punctuation each failed PostgresImagePin with the static-atom refusal; a hole reading a combining-mark runtime identifier passed. Restored, rebuilt, all three SchemaDocsTests green.
1 parent 54c6671 commit 762a0d6

1 file changed

Lines changed: 15 additions & 1 deletion

File tree

tests/Cluckwork.Api.IntegrationTests/SchemaDocsTests.cs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1141,6 +1141,20 @@ private static int SkipTrivia(string t, int p)
11411141
// matching close paren, or -1 when the interior carries anything else
11421142
// (an operator, a quote): that is an expression, not a type. A `)` or
11431143
// `>` that closes what is not open is malformed and also -1.
1144+
// C# identifier characters, per the language's identifier-part
1145+
// categories — IsLetterOrDigit alone misses letter numbers, connector
1146+
// punctuation, combining marks, and format characters, all of which are
1147+
// legal in identifiers (and therefore in type names and tuple element
1148+
// names) as LITERAL characters, not only as \u escapes.
1149+
private static bool IsCSharpIdentifierChar(char c) =>
1150+
char.IsLetterOrDigit(c)
1151+
|| c == '_'
1152+
|| char.GetUnicodeCategory(c) is System.Globalization.UnicodeCategory.LetterNumber
1153+
or System.Globalization.UnicodeCategory.ConnectorPunctuation
1154+
or System.Globalization.UnicodeCategory.NonSpacingMark
1155+
or System.Globalization.UnicodeCategory.SpacingCombiningMark
1156+
or System.Globalization.UnicodeCategory.Format;
1157+
11441158
private static int TryConsumeTypeParen(string t, int p)
11451159
{
11461160
var parenDepth = 1;
@@ -1183,7 +1197,7 @@ static bool Hex(string s, int start, int count)
11831197
if (p + 1 < t.Length && t[p + 1] == 'U' && Hex(t, p + 2, 8)) { p += 10; continue; }
11841198
return -1;
11851199
}
1186-
else if (!(char.IsLetterOrDigit(c) || c is '_' or '.' or ':' or ',' or '?' or '[' or ']' or '*' or '@'))
1200+
else if (!(IsCSharpIdentifierChar(c) || c is '.' or ':' or ',' or '?' or '[' or ']' or '*' or '@'))
11871201
return -1;
11881202
p++;
11891203
}

0 commit comments

Comments
 (0)