平台接線護欄
修改 SqlAssist.Ssms22 接線、事件、命令、UI、MEF、連線或部署前必讀。
禁止在背景工作裡直接改編輯器緩衝區。非同步替換一律走
Editor/TextViewEditCoordinator:切 UI 執行緒、檢查編輯器已關閉、從ITrackingSpan取最新範圍、確認原文還在原處,少一道就會覆蓋使用者的輸入。禁止在 Ssms22 的平台邊界自己寫
try/catch——MEF 建立方法、編輯器事件、 按鍵處理常式、派送佇列上的工作、沒有人接結果的背景工作,一律走SqlAssistPlatformGuard:方法 用在哪 失敗時 Run/RunAsync/CreateMEF 建立、按鍵、編輯器事件、派送工作 WriteAlways完整堆疊、送一則失敗通知(UnexpectedFailureNotice)並回傳替代值Probe佈景筆刷、DPI、游標位置、錨點座標等會連續失敗的可選探測 只在詳細診斷記一行 Begin/BeginProbe沒有人接結果的背景工作;後者用於預載、預熱,以及逾時放掉等待、仍在跑的工作(傳 Task,不必壓 VSTHRD003)依前兩族的層級處理 禁止用
Run記錄會連續失敗的探測,紀錄檔會被灌滿而蓋掉真正的錯誤。取消通常視為正常 結束;只有RunPropagatingCancellation必須把取消狀態交回平台,否則過期內容會被當成有效答案。 替代值用Func<T>,成功時不必先算昂貴的完整候選清單。禁止用 Guard 吞掉 Core 與 Metadata 的商業邏輯錯誤。以下四類刻意不走 Guard,並在該處註明理由: 使用者主動觸發、失敗必須看見的(工具命令、預覽狀態列、片段管理員與 F12,每一句訊息都不同);
SqlAssistPackage載入失敗(記錄後重擲,讓殼層知道套件未載入);有例外篩選的預期失敗(例如 片段存放區只接檔案系統錯誤);SqlAssistDiagnostics本身(Guard 的錯誤正要寫到這裡)。禁止在按鍵或滑鼠移動路徑上同步查詢資料庫。沒命中快取就這一輪不顯示, 背景補上之後下一次就有。
禁止在 QuickInfo 路徑向 SSMS 詢問目前連線——那個呼叫有 UI 執行緒相依性。
UI 親和性由被呼叫的那一端自保。包裝宿主服務的非同步方法進場就
SwitchToMainThreadAsync(已經在上面時同步完成,不花錢),禁止改成「在回傳前切回去 讓呼叫端接手」:續程落在哪一條執行緒是呼叫端的await決定的,一個ConfigureAwait(false)就把那個保證作廢,而且只在中間真的 await 過的那幾條路上發作。 同步方法切不了執行緒,維持ThrowIfNotOnUIThread。自保的那幾支禁止用JoinableTaskFactory.Run同步等待。完整推導見結果導航的執行緒分工。 這一條現在由VSTHRD109在編譯期擋著:非同步方法裡寫ThrowIfNotOnUIThread直接是 error。分析器開了哪幾條、關了哪幾條與理由見.editorconfig。要把續程留在 UI 執行緒時明寫
ConfigureAwait(true):這個專案滿是ConfigureAwait(false),留空的那一個看起來像漏掉的。禁止只靠
Caret.PositionChanged追游標情境:游標跟著編輯位移(打字、刪字、復原、 背景寫回)時平台不發這個事件。要一併聽文字變更;跟著游標的提示一律走Editor/CaretHint。禁止依賴
CommitBehavior.Retrigger:SSMS 22 的編輯器組件沒有任何一處讀它。禁止用
DismissAllSessions搶 session。重開清單一律走SqlCompletionReopen的三步驟(Dismiss → TriggerCompletion → OpenOrUpdate),一步都不能少。禁止在原地重開建議清單;必須排到派送佇列的 Background 優先權。
禁止在浮動預覽裡內嵌真正的編輯器,或依賴
ApplicationCommands.Copy的繞送。禁止用
Window.GetWindow找元素所在的視窗,一律SsmsWindows.WindowOf:編輯器在 HwndHost 裡、 Popup 是自己的頂層 HWND,前者都回傳 null 而且不報錯。BannedSymbols.txt在編譯期擋著(RS0030); 平台上其他「安靜回傳 null」的 API 也加進那份清單,不靠記憶。StaysOpen的 Popup 裡有要鍵盤的控制項時,按下的預覽階段必須先SsmsWindows.ActivateFrameOf: Popup 被點不啟用程式,SSMS 在背景時鍵盤焦點進不去,只剩滑鼠操作能動。禁止在
UI/SqlAssistChrome之外另立一套外觀。字型、字級推導、按鈕、輸入欄位、 核取方塊與資料格樣板只有那一個來源;Preview/PreviewChrome只放別的視窗用不到的東西。 排版與視覺判準見自製 UI 準則。禁止用現代編輯器的
ICommandHandler接殼層命令(F12 之類):命令到不了現代管線。 走命令表的鍵繫結或Editor/SqlShellCommandFilter;濾鏡必須在QueryStatus回報 supported+enabled,且在轉傳之前禁止做 GUID 比對與一次靜態旗標讀取以外的任何事—— 每個按鍵都走過那裡。理由與排查見殼層命令。禁止改了
Menus.vsct卻沒把ProvideMenuResource的版號加一,也禁止改完命令表後 用Deploy-DebugExtension.ps1部署,一律Install-Extension.ps1重新安裝:pkgdef 不在部署 清單裡,新選單與新鍵繫結會安靜地不生效。禁止讓命令自己算可見度(
BeforeQueryStatus設Visible)卻沒在命令表標上DynamicVisibility與DefaultInvisible:殼層會照樣顯示,沒有例外也沒有紀錄。tools/Test-CommandTable.ps1會比對兩邊。禁止搬動 MEF 匯出型別的命名空間後繞過
Deploy-DebugExtension.ps1手動複製 DLL:MEF 快取 記完整型別名稱,部件會安靜地建立失敗。記錄檔沒有「SQL 編輯器已建立」就是快取過期, 見偵錯。