From 7979568165075c2f3b1f3d61cf2ee8f66a4b9d63 Mon Sep 17 00:00:00 2001 From: Jon Kazama Date: Tue, 26 May 2026 14:04:46 +0200 Subject: [PATCH] refactor(ipc): drop this.-qualifier and trim BuildState comments Same shadowing-via-instance-property as Plugin.CurrentTab above. Comments trimmed to default 1-3 line density; security/threading WHY-blocks earn their lines when they document non-obvious invariants, not standard C# name resolution. --- HellionChat/Ipc/TypingIpc.cs | 29 ++++++----------------------- 1 file changed, 6 insertions(+), 23 deletions(-) diff --git a/HellionChat/Ipc/TypingIpc.cs b/HellionChat/Ipc/TypingIpc.cs index 0275143..57d36b2 100644 --- a/HellionChat/Ipc/TypingIpc.cs +++ b/HellionChat/Ipc/TypingIpc.cs @@ -70,30 +70,13 @@ internal sealed class TypingIpc : IDisposable : usedChannel.Channel; var channelType = inputChannel.ToChatType(); - // `Plugin` here is the instance property on TypingIpc (TypingIpc.cs:18 - // `private Plugin Plugin { get; }`), NOT the type `HellionChat.Plugin`. - // C# resolves `Plugin.MainWindow` as `this.Plugin.MainWindow` because - // the instance property shadows the type name inside this class. Do - // NOT switch to a type-qualified read (CS0120 — `MainWindow` is an - // instance member, not a static one). MainWindow is resolved in Phase-1 - // (Plugin.cs:295) and never re-assigned, so `this.Plugin.MainWindow` - // is non-null by the time TypingIpc.Update() runs (HostedServices only - // start after Phase-1). The `null!`-suppression on the MainWindow - // property would let us drop the `?.`, but a null-safe read costs - // nothing at runtime and shields against a theoretical pre-Phase-1 - // caller (a future IPC-pull that fires before HostedServices start). - // Defense in depth, no behaviour change for the production path. - var mainWindowOpen = this.Plugin.MainWindow?.IsOpen ?? false; + // MainWindow is Phase-1-resolved and never reassigned; + // the `?.` is defense-in-depth for pre-Phase-1 IPC-pulls. + var mainWindowOpen = Plugin.MainWindow?.IsOpen ?? false; - // Stale-state guard: InputBar._isFocused is only written in DrawInputField, - // which only runs while MainWindow is open. After the user closes the - // window, _isFocused freezes on the last value. _pendingMessage has the - // same stale problem — it is only cleared in TrySend (successful send) - // or ClearBuffer (manual reset), so closing MainWindow with non-empty - // buffer leaves PendingLength frozen above zero. Without gating all - // four state fields on mainWindowOpen, Cross-Plugin-Subscribers would - // keep seeing InputFocused: true / HasText: true / IsTyping: true / - // TextLength: N even though no input field exists. + // Stale-state guard: InputBar's focus and pending-buffer fields are + // only written by DrawInputField. Closing MainWindow freezes them, so + // gate all four state fields on mainWindowOpen. var inputFocused = mainWindowOpen && _inputBar.IsFocused; var hasText = mainWindowOpen && _inputBar.PendingLength > 0; var textLength = mainWindowOpen ? _inputBar.PendingLength : 0;