片段自訂、合併與存檔
本頁包含內建值與使用者 override 的合併、版本相容與存檔,以及手改檔案帶進來的違規。 樣板語法與 Tab 導航見片段導航。
內建值與使用者 override
內建定義只有一份: src/SqlAssist.Core/Snippets/DefaultSnippets.json,以 Embedded Resource 隨 VSIX 發布。 不要把 49 筆內容寫進 C#,也不要放進 VSIX 安裝步驟複製到使用者目錄。 其他語言的標題、說明與欄位提示疊自 DefaultSnippets.<語言>.json(見在地化)。
使用者 override 一律蓋過內建值,不論語言:存下來的就是使用者當時看到的文字。反過來,存檔時與任何一個語言的 內建值相同都不算自訂(SqlSnippetDefaults.IsUnmodifiedBuiltIn):清單在繁中載入、換成英文後才存檔時,沒改過的 49 筆仍是繁中文字,只和目前語言比會全部寫進使用者檔,之後就跟不上新版的內建值。
使用者檔位於 %APPDATA%\SqlAssist\snippets.json,v2 只存:
- 修改過的內建項目;
{ "id": "builtin...", "disabled": true }的停用紀錄;- 使用者新增的完整項目。
檔案不存在代表「完全使用內建值」,不會在第一次啟動時建檔。這讓新版 VSIX 可以直接 更新未自訂的內建片段。管理介面會標示「已自訂」與「已停用」,並提供「還原此預設」; 全部還原後寫出的 override 清單是空的。
{
"version": 2,
"snippets": [
{
"id": "builtin.ctb",
"category": "ddl",
"shortcut": "ctb",
"title": "CREATE TABLE",
"description": "建立資料表",
"expansionMode": "tabStops",
"positions": ["StatementStart", "BlockStart"],
"code": "CREATE TABLE $schema$.$table$\n(\n $column$ $dataType$ NOT NULL\n)$end$;",
"placeholders": [
{ "id": "schema", "default": "dbo", "tooltip": "結構描述" },
{ "id": "table", "default": "TableName", "tooltip": "資料表名稱" },
{ "id": "column", "default": "ColumnName", "tooltip": "欄位名稱" },
{ "id": "dataType", "default": "INT", "tooltip": "資料型別" }
]
},
{ "id": "builtin.dt", "disabled": true }
]
}category 是固定集合:select、dml、ddl、controlFlow、clause、other; 不認得的值落到 other。positions 重用 SqlKeywordPosition;缺席、空陣列或名稱 全都不認得都是 Any(哪裡都能用)。明寫 "None" 的意思與關鍵字相同:只在分析器 判不出位置時出現。
positions 給得太緊的症狀是全靜默的:使用者只覺得「這個片段有時候有、 有時候沒有」。語句級片段一律要同時給 StatementStart 與 BlockStart——分析器在 BEGIN 之後只回報 BlockStart,只給前者的話整批片段在 BEGIN…END 區塊裡會消失。 守門的是 SqlSnippetDefaultsTests.內建片段在它自然的位置找得到;新增片段時 要在那份表格加一行。
minimumSqlServerVersion 不存在:產品下限已固定,為它查詢每條連線的版本只會把資料庫 I/O 帶進按鍵路徑。
版本、相容與存檔
- 沒有 v1 遷移路徑。 v1 是完整清單、且第一次啟動就建檔,但它只在 0.14.22 這一個 版本外流一天;為它留著凍結快照與整套等價比較不划算。
version缺席或小於 2 一律照 v2 讀:手改檔案經常不寫版本,留一個讀不動的版本號只會讓整份進唯讀,使用者卻沒有可以照做 的修法。代價是真的還留著 v1 檔的人,那三筆沒有id的項目會變成自訂片段並遮住同捷徑 的內建定義——刪掉snippets.json就回到全內建。 version > 2時可以讀已知欄位,但整份進入唯讀模式,避免舊版把新欄位覆蓋掉。- v2 保留頂層
snippets鍵並只新增欄位;降回舊版時,舊讀取器至少仍看得到完整 override 與自訂項目。 - 存檔先寫同目錄暫存檔,再用
File.Replace原子置換;目標不存在時才用File.Move。 - 允許 JSON 註解與尾隨逗號。整份語法壞掉時保留原檔、切成唯讀、顯示錯誤,並繼續提供內建片段。
手改檔案帶進來的單筆違規
只看一份樣板就能判斷的兩條規則(捷徑的格式與 T-SQL 關鍵字撞名、包夾錨點 $surround$ 只能出現一次)在 SqlSnippetValidation:管理介面存檔前擋下, SqlSnippetMerger.Merge 載入時重跑同一份。手改檔案繞得過前者,所以兩邊必須是 同一個進入點——分岔的症狀是清單上沒有標記的那一筆,按下儲存時突然被退回。
載入端只回報不修資料:那一筆照樣留在管理清單與一般建議裡(無效錨點不能用於 包夾),SqlSnippetStore 記進診斷, 管理介面在標題標成「不符規則」(與「已停用」「已遮住」同一排)、開啟時報出筆數、 選起來看原因。整份切唯讀是留給「JSON 壞掉」的處置,單筆違規沒有那麼重; 而安靜地丟掉那一筆更糟——使用者會發現片段消失卻沒有任何說明。
撞名不算違規:那是計算結果,由「已遮住」表示,改掉撞名的那一筆就自己解除。
不使用檔案監看器:清單只在第一次使用時載入並維持穩定參考,管理介面成功存檔才換快照。 因此按鍵路徑沒有磁碟 I/O,也不會因每次 Current 產生新物件而重建整批建議。直接用文字 編輯器修改 JSON 後,需要重新啟動 SSMS 才會載入。
這是 SqlAssist 自己的格式,與 SSMS「程式碼片段管理員」的 .snippet 檔不互相註冊; 只有提交時把選到的項目轉成記憶體中的原生 XML。