Skip to content

Commit 3287b91

Browse files
dkattanCopilot
andcommitted
fix: narrow workspace PS path usage
Use direct file I/O for file-backed documents and filesystem traversal for file-backed workspace folders, while preserving PowerShell-backed behavior for provider URIs. This avoids cross-thread/apartment host invocations for ordinary workspace requests and keeps provider-backed paths working. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent ea55e6b commit 3287b91

1 file changed

Lines changed: 31 additions & 9 deletions

File tree

src/PowerShellEditorServices/Services/Workspace/WorkspaceService.cs

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,8 @@ public WorkspaceService(ILoggerFactory factory, PsesInternalHost psesInternalHos
117117

118118
#region Public Methods
119119

120-
public IEnumerable<string> WorkspacePaths => WorkspaceFolders.Select(i => i.Uri.GetFileSystemPath());
120+
public IEnumerable<string> WorkspacePaths => WorkspaceFolders.Select(
121+
folder => folder.Uri.ToUri().IsFile ? folder.Uri.GetFileSystemPath() : GetPowerShellPath(folder.Uri));
121122

122123
/// <summary>
123124
/// Gets an open file in the workspace. If the file isn't open but exists on the filesystem, load and return it.
@@ -391,21 +392,26 @@ public IEnumerable<string> EnumeratePSFiles(
391392
int maxDepth,
392393
bool ignoreReparsePoints)
393394
{
394-
string[] workspacePaths = GetPowerShellWorkspacePaths()
395+
string[] powerShellWorkspacePaths = GetPowerShellWorkspacePaths()
395396
.Where(path => !string.IsNullOrEmpty(path))
396397
.Distinct(StringComparer.OrdinalIgnoreCase)
397398
.ToArray();
398399

399-
if (workspacePaths.Length == 0)
400+
string[] fileSystemWorkspacePaths = GetFileSystemWorkspacePaths()
401+
.Where(path => !string.IsNullOrEmpty(path))
402+
.Distinct(StringComparer.OrdinalIgnoreCase)
403+
.ToArray();
404+
405+
if (powerShellWorkspacePaths.Length == 0 && fileSystemWorkspacePaths.Length == 0)
400406
{
401407
yield break;
402408
}
403409

404-
if (psesInternalHost is not null)
410+
if (psesInternalHost is not null && powerShellWorkspacePaths.Length > 0)
405411
{
406412
PSCommand psCommand = new PSCommand()
407413
.AddCommand(@"Microsoft.PowerShell.Management\Get-ChildItem")
408-
.AddParameter("LiteralPath", workspacePaths)
414+
.AddParameter("LiteralPath", powerShellWorkspacePaths)
409415
.AddParameter("Recurse")
410416
.AddParameter("ErrorAction", ActionPreference.SilentlyContinue)
411417
.AddParameter("Force")
@@ -437,7 +443,7 @@ public IEnumerable<string> EnumeratePSFiles(
437443
foreach (string pattern in includeGlobs) { matcher.AddInclude(pattern); }
438444
foreach (string pattern in excludeGlobs) { matcher.AddExclude(pattern); }
439445

440-
foreach (string rootPath in workspacePaths)
446+
foreach (string rootPath in fileSystemWorkspacePaths)
441447
{
442448
if (!Directory.Exists(rootPath))
443449
{
@@ -478,7 +484,7 @@ internal static StreamReader OpenStreamReader(DocumentUri uri)
478484

479485
internal string ReadFileContents(DocumentUri uri)
480486
{
481-
if (psesInternalHost is null)
487+
if (uri.ToUri().IsFile || psesInternalHost is null)
482488
{
483489
using StreamReader reader = OpenStreamReader(uri);
484490
return reader.ReadToEnd();
@@ -506,18 +512,34 @@ internal string ReadFileContents(DocumentUri uri)
506512
}
507513
}
508514

509-
private IEnumerable<string> GetPowerShellWorkspacePaths()
515+
private IEnumerable<string> GetFileSystemWorkspacePaths()
510516
{
511517
if (WorkspaceFolders.Count > 0)
512518
{
513-
return WorkspaceFolders.Select(folder => GetPowerShellPath(folder.Uri));
519+
return WorkspaceFolders
520+
.Select(folder => folder.Uri)
521+
.Where(uri => uri.ToUri().IsFile)
522+
.Select(uri => uri.GetFileSystemPath());
514523
}
515524

516525
return string.IsNullOrEmpty(InitialWorkingDirectory)
517526
? Array.Empty<string>()
518527
: new[] { InitialWorkingDirectory };
519528
}
520529

530+
private IEnumerable<string> GetPowerShellWorkspacePaths()
531+
{
532+
if (WorkspaceFolders.Count > 0)
533+
{
534+
return WorkspaceFolders
535+
.Select(folder => folder.Uri)
536+
.Where(uri => !uri.ToUri().IsFile)
537+
.Select(GetPowerShellPath);
538+
}
539+
540+
return Array.Empty<string>();
541+
}
542+
521543
private static string ConvertWorkspaceItemPath(PSObject item)
522544
{
523545
if (item.Properties["FullName"]?.Value is string fullName && !string.IsNullOrEmpty(fullName))

0 commit comments

Comments
 (0)