Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
chore(mocks): tighten EscapeIdentifier visibility, document GetWrappe…
…rName decision

Round-2 review feedback on #5679:
- IdentifierEscaping.EscapeIdentifier is now `internal` (was misleadingly
  `public` inside an internal class).
- Added a one-line WHY comment above MockMembersBuilder.GetWrapperName
  explaining that embedding the raw method name into the compound
  wrapper identifier is intentional — a keyword as a non-terminal
  substring is valid C#, so EscapeIdentifier is not needed there.
  • Loading branch information
thomhurst committed Apr 23, 2026
commit 9fd285d39de66858b364f4a4777e900f8116732b
5 changes: 5 additions & 0 deletions TUnit.Mocks.SourceGenerator/Builders/MockMembersBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,11 @@ private static bool ShouldGenerateTypedWrapper(MockMemberModel method, bool hasE
return matchableParams.Count <= MaxTypedParams;
}

// method.Name is intentionally embedded raw (unescaped) here. The result is a compound
// identifier like "IFoo_event_M2_MockCall" — even when method.Name is a C# keyword such as
// "event" or "class", it appears only as a non-terminal substring of a larger token, which is
// a valid C# identifier. Escaping (via EscapeIdentifier) is only required when the name would
// stand alone as a complete identifier in the emitted source.
private static string GetWrapperName(string safeName, MockMemberModel method)
=> $"{safeName}_{method.Name}_M{method.MemberId}_MockCall";

Expand Down
2 changes: 1 addition & 1 deletion TUnit.Mocks.SourceGenerator/IdentifierEscaping.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ internal static class IdentifierEscaping
// C# compiler already disambiguates them by position. Escaping a contextual keyword would
// change the identifier's textual form (e.g. `record` → `@record`), breaking explicit
// interface implementation matching against the source-declared member name.
public static string EscapeIdentifier(string name) =>
internal static string EscapeIdentifier(string name) =>
SyntaxFacts.GetKeywordKind(name) != SyntaxKind.None ? "@" + name : name;
}
Loading