Shorten Peek Definition tab names - #2807
Conversation
Peek Definition wrote each generated script to a file named "<db>.<schema>.<object>_<32 hex GUID>.sql", and VS Code labels a tab with the file name, so a handful of open definitions filled the tab strip with unreadable titles. The GUID also meant every request produced a new file, so asking for the same definition twice opened a second tab for it. Name the file after the object instead. A given object keeps one file for the life of the process, so a repeated request refreshes the tab already open. Two different objects that want the same name, which happens when one qualified name resolves against two connections, are separated by a numeric suffix. The GUID was also doing real work: it was added to make these APIs parallel safe, since definition requests run concurrently and would otherwise write the same path at once. That is now handled directly, by taking a per-file lock around the write and by reading the lines from the generated script rather than back off disk. A write is skipped entirely when the file already holds the same script, so an editor with the definition open is left alone. Object identity is compared case sensitively, because a case sensitive collation can hold both "Foo" and "foo" and giving them one file would show the wrong definition for one of them. Characters that are legal in a quoted identifier but not in a file name are replaced, which the GUID never guarded against.
There was a problem hiding this comment.
Pull request overview
This PR updates Peek Definition script file naming to remove the per-request GUID suffix so VS Code editor tab titles remain short and repeated requests reuse the same tab/file within a process, while preserving parallel-safety via per-file write locking and stable per-object name assignment.
Changes:
- Replace GUID-suffixed Peek Definition filenames with stable, object-derived names (and numeric suffixes to avoid collisions).
- Add in-process synchronization and “skip write if unchanged” behavior when writing definition files under parallel request handling.
- Add new unit tests covering name assignment, sanitization, and concurrent naming/writing behavior.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| test/Microsoft.SqlTools.ServiceLayer.UnitTests/LanguageServer/PeekDefinitionTests.cs | Updates existing test to assert stable names for the same object. |
| test/Microsoft.SqlTools.ServiceLayer.UnitTests/LanguageServer/PeekDefinitionFileNameTests.cs | Adds comprehensive tests for filename assignment, sanitization, and concurrent behavior. |
| src/Microsoft.SqlTools.LanguageService/Scripting/ScripterCore.cs | Implements new naming API, per-file locking, and avoids disk read-back for line scanning. |
| src/Microsoft.SqlTools.LanguageService/Scripting/PeekDefinitionFileNames.cs | New helper for stable per-identity naming, collision suffixing, and invalid-character sanitization. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
… names and improve script generation logic
There was a problem hiding this comment.
🟢 Approval recommended
The functional change is well-covered by new unit tests and appears correct; only a minor misleading comment should be adjusted.
Review details
- Files reviewed: 4/4 changed files
- Comments generated: 1
- Review effort level: Lite
| // A missing object produces no script. Treat that the same as the empty file written | ||
| // by the previous implementation so the caller can return an empty location list. |
There was a problem hiding this comment.
🔵 Needs a closer look
The new filename sanitization can still produce Windows-invalid names (trailing spaces/periods), which can prevent script files from being created.
Review details
Suppressed comments (2)
Previously missed (1) — in code that hasn't changed since the last review.
src/Microsoft.SqlTools.LanguageService/Scripting/PeekDefinitionFileNames.cs:136
- SanitizeBaseName only replaces Path.GetInvalidFileNameChars() and checks reserved device names, but it can still return names that are invalid on Windows because file names cannot end with a space or period (e.g., object name "CON." or "name "). This can still happen even after prefixing reserved names, resulting in a file that cannot be created on Windows.
src/Microsoft.SqlTools.LanguageService/Scripting/ScripterCore.cs:310
- The new comment says an object with no script is treated so the caller can return an empty location list, but this method actually sets error state and returns null in that case. The comment should match the actual behavior (or the behavior should be updated to return an empty array if that’s intended).
// A missing object produces no script. Treat that the same as the empty file written
// by the previous implementation so the caller can return an empty location list.
string script = operation.ScriptText ?? string.Empty;
- Files reviewed: 4/4 changed files
- Comments generated: 0 new
- Review effort level: Lite
Description
Shortens Peek Definition tab names by replacing the GUID suffix with stable object-based file names. Repeated requests for the same object reuse the existing tab, while collisions receive a numeric suffix such as
_2.The change preserves parallel safety with per-file write locks, avoids rewriting unchanged scripts, keeps the resolved database in the internal collision identity without adding it to unqualified tab names, and sanitizes invalid or Windows-reserved file names.
Fixes microsoft/vscode-mssql#22785
Code Changes Checklist
dotnet test)Reviewers: Please read our reviewer guidelines