Skip to content

Commit dd265d9

Browse files
authored
Ensure unique file paths for non-file Uris (#12037)
Bug: microsoft/vscode-dotnettools#2151 (deliberately not marking this PR as a fix due to DevKit process) When an active agent chat session is open, VS Code will send LSP requests for files with the `chat-editing-text-model://` scheme, similar to how the left hand side of a diff view uses `git://`. This causes problems during editing because we end up getting didChange messages for Uris with that scheme, and Uris with the file scheme, which means we end up with two didChanges for the same physical file. This PR expands the fix we previously had specifically for `git://` Uris, to apply to any non-file Uri. It essentially ensures these documents are always in the misc files project, so we'll still be able to generally deal with them, we just won't get confused by them. As I noted in a comment, a better fix would be to stop using file paths, but instead use the Uris provided by the LSP client as the source of truth, but given the size and risk of that change (would mean Uri/DocumentUri as a key in `ProjectSnapshotManager`) and the fact that cohosting effectively delivers this via Roslyn anyway, it didn't seem prudent or worth it for this specific issue.
2 parents b8752a0 + 387d7cf commit dd265d9

File tree

2 files changed

+22
-10
lines changed

2 files changed

+22
-10
lines changed

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/UriExtensions.cs

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,25 +37,36 @@ public static string GetAbsoluteOrUNCPath(this Uri uri)
3737
// Absolute paths are usually encoded.
3838
var absolutePath = uri.AbsolutePath.Contains("%") ? WebUtility.UrlDecode(uri.AbsolutePath) : uri.AbsolutePath;
3939

40-
if (string.Equals(uri.Scheme, "git", StringComparison.OrdinalIgnoreCase))
41-
{
42-
// return a normalized path when we want to add to a fake git directory path (hacky fix for https://github.com/dotnet/razor/issues/9365)
43-
return AddToFakeGitDirectoryAtRoot(absolutePath);
44-
}
45-
46-
return absolutePath;
40+
return EnsureUniquePathForScheme(uri.Scheme, absolutePath);
4741
}
4842

49-
private static string AddToFakeGitDirectoryAtRoot(string decodedAbsolutePath)
43+
private static string EnsureUniquePathForScheme(string scheme, string decodedAbsolutePath)
5044
{
45+
// File Uris we leave untouched, as they represent the actual files on disk
46+
if (scheme == Uri.UriSchemeFile)
47+
{
48+
return decodedAbsolutePath;
49+
}
50+
5151
var normalizedPath = FilePathNormalizer.Normalize(decodedAbsolutePath);
5252
var firstSeparatorIndex = normalizedPath.IndexOf('/');
5353
if (firstSeparatorIndex < 0)
5454
{
55-
// no-op
55+
// A path without a separator is unlikely, but we can't add our unique-ness marker anyway, so just return as is
56+
// and hope for the best.
5657
return decodedAbsolutePath;
5758
}
5859

59-
return normalizedPath.Insert(firstSeparatorIndex + 1, "_git_/");
60+
// For any non-file Uri, we add a marker to the path to ensure things won't conflict with the real file on disk.
61+
// This is a somewhat hacky fix to ensure things like a git diff view will work, where the left hand side is a
62+
// Uri like "git://path/to/file.razor" and the right hand side is "file://path/to/file.razor". If we mapped both
63+
// of those to the same file path, then one side would be sending line and character positions that don't match
64+
// our understanding of the document.
65+
// A true fix would be to move away from using file paths in the first place, but instead use the Uris as provided
66+
// by the LSP client as the source of truth.
67+
// See https://github.com/dotnet/razor/issues/9365 and https://github.com/microsoft/vscode-dotnettools/issues/2151
68+
// for examples.
69+
70+
return normalizedPath.Insert(firstSeparatorIndex + 1, $"_{scheme}_/");
6071
}
6172
}

src/Razor/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/UriExtensionsTest.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ public void GetAbsoluteOrUNCPath_AbsolutePath_HandlesSpacePaths()
6060
[InlineData(@"git:/c%3A/path/to/dir/Index.cshtml", @"c:/_git_/path/to/dir/Index.cshtml")]
6161
[InlineData(@"git:/c:/path%2Fto/dir/Index.cshtml?%7B%22p", @"c:/_git_/path/to/dir/Index.cshtml")]
6262
[InlineData(@"git:/c:/path/to/dir/Index.cshtml", @"c:/_git_/path/to/dir/Index.cshtml")]
63+
[InlineData(@"chat-editing-text-model:/c:/path/to/dir/Index.cshtml", @"c:/_chat-editing-text-model_/path/to/dir/Index.cshtml")]
6364
public void GetAbsoluteOrUNCPath_AbsolutePath_HandlesGitScheme(string filePath, string expected)
6465
{
6566
// Arrange

0 commit comments

Comments
 (0)